using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.Logging; using Moq; using Nacos.V2; using Nacos.V2.Common; using Nacos.V2.Naming.Dtos; using System.Net.Http; using System.Net.Http.Json; using System.Threading.Tasks; using Xunit; namespace Microservice.Common.Tests { public class ServiceClientTests { private readonly Mock _nacosNamingServiceMock; private readonly HttpClient _httpClient; private readonly Mock> _loggerMock; private readonly ServiceClient _serviceClient; public ServiceClientTests() { // 初始化模拟对象 _nacosNamingServiceMock = new Mock(); _loggerMock = new Mock>(); // 创建一个测试用的 HttpClient var httpClientHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true }; _httpClient = new HttpClient(httpClientHandler); // 创建 ServiceClient 实例 _serviceClient = new ServiceClient(_nacosNamingServiceMock.Object, _loggerMock.Object); } [Fact] public async Task GetAsync_ShouldReturnSuccess_WhenServiceIsAvailable() { // Arrange var serviceName = "TestService"; var endpoint = "/api/test"; var expectedResponse = new { Message = "Test Response" }; // 模拟 Nacos 服务发现返回一个健康的实例 var instance = new Instance { Ip = "127.0.0.1", Port = 8080, Healthy = true, Enabled = true }; _nacosNamingServiceMock.Setup(x => x.SelectOneHealthyInstance(serviceName)).ReturnsAsync(instance); // 创建一个测试服务器 var testServer = new TestServer(new WebApplicationFactory().WithWebHostBuilder(builder => { builder.ConfigureServices(services => { // 配置测试服务 }); builder.Configure(app => { app.MapGet("/api/test", () => Results.Ok(expectedResponse)); }); })); // 使用测试服务器的 HttpClient var testHttpClient = testServer.CreateClient(); var testServiceClient = new ServiceClient(_nacosNamingServiceMock.Object, testHttpClient, _loggerMock.Object); // Act var result = await testServiceClient.GetAsync(serviceName, endpoint); // Assert Assert.NotNull(result); Assert.Equal(expectedResponse.Message, ((dynamic)result).Message); } [Fact] public async Task GetAsync_ShouldThrowException_WhenServiceIsNotAvailable() { // Arrange var serviceName = "NonExistentService"; var endpoint = "/api/test"; // 模拟 Nacos 服务发现返回 null _nacosNamingServiceMock.Setup(x => x.SelectOneHealthyInstance(serviceName)).ReturnsAsync((Instance)null); // Act & Assert await Assert.ThrowsAsync(() => _serviceClient.GetAsync(serviceName, endpoint)); } [Fact] public async Task GetAsync_ShouldHandleDifferentEndpointFormats() { // Arrange var serviceName = "TestService"; var expectedResponse = new { Message = "Test Response" }; // 模拟 Nacos 服务发现返回一个健康的实例 var instance = new Instance { Ip = "127.0.0.1", Port = 8080, Healthy = true }; _nacosNamingServiceMock.Setup(x => x.SelectOneHealthyInstance(serviceName)).ReturnsAsync(instance); // 创建测试服务器 var testServer = new TestServer(new WebApplicationFactory().WithWebHostBuilder(builder => { builder.Configure(app => { app.Run(async context => { // 验证请求路径是否以 '/' 开头 Assert.StartsWith("/", context.Request.Path); await context.Response.WriteAsJsonAsync(new { StatusCode = 200, Message = "Success", Data = expectedResponse }); }); }); })); // 测试不同格式的端点 var endpoints = new[] { "/api/test", "api/test", "test", "/test" }; foreach (var endpoint in endpoints) { // Act & Assert var result = await _serviceClient.GetAsync(serviceName, endpoint); Assert.NotNull(result); } } [Fact] public async Task PostAsync_ShouldReturnSuccess_WhenServiceIsAvailable() { // Arrange var serviceName = "TestService"; var endpoint = "/api/test"; var requestData = new { Name = "Test" }; var expectedResponse = new { Message = "Test Response" }; // 模拟 Nacos 服务发现返回一个健康的实例 var instance = new Instance { Ip = "127.0.0.1", Port = 8080, Healthy = true, Enabled = true }; _nacosNamingServiceMock.Setup(x => x.SelectOneHealthyInstance(serviceName)).ReturnsAsync(instance); // 创建一个测试服务器 var testServer = new TestServer(new WebApplicationFactory().WithWebHostBuilder(builder => { builder.Configure(app => { app.MapPost("/api/test", (object data) => Results.Ok(expectedResponse)); }); })); // 使用测试服务器的 HttpClient var testHttpClient = testServer.CreateClient(); var testServiceClient = new ServiceClient(_nacosNamingServiceMock.Object, testHttpClient, _loggerMock.Object); // Act var result = await testServiceClient.PostAsync(serviceName, endpoint, requestData); // Assert Assert.NotNull(result); Assert.Equal(expectedResponse.Message, ((dynamic)result).Message); } [Fact] public async Task PutAsync_ShouldReturnSuccess_WhenServiceIsAvailable() { // Arrange var serviceName = "TestService"; var endpoint = "/api/test"; var requestData = new { Name = "Test" }; var expectedResponse = new { Message = "Test Response" }; // 模拟 Nacos 服务发现返回一个健康的实例 var instance = new Instance { Ip = "127.0.0.1", Port = 8080, Healthy = true, Enabled = true }; _nacosNamingServiceMock.Setup(x => x.SelectOneHealthyInstance(serviceName)).ReturnsAsync(instance); // 创建一个测试服务器 var testServer = new TestServer(new WebApplicationFactory().WithWebHostBuilder(builder => { builder.Configure(app => { app.MapPut("/api/test", (object data) => Results.Ok(expectedResponse)); }); })); // 使用测试服务器的 HttpClient var testHttpClient = testServer.CreateClient(); var testServiceClient = new ServiceClient(_nacosNamingServiceMock.Object, testHttpClient, _loggerMock.Object); // Act var result = await testServiceClient.PutAsync(serviceName, endpoint, requestData); // Assert Assert.NotNull(result); Assert.Equal(expectedResponse.Message, ((dynamic)result).Message); } [Fact] public async Task DeleteAsync_ShouldReturnSuccess_WhenServiceIsAvailable() { // Arrange var serviceName = "TestService"; var endpoint = "/api/test"; var expectedResponse = new { Message = "Test Response" }; // 模拟 Nacos 服务发现返回一个健康的实例 var instance = new Instance { Ip = "127.0.0.1", Port = 8080, Healthy = true, Enabled = true }; _nacosNamingServiceMock.Setup(x => x.SelectOneHealthyInstance(serviceName)).ReturnsAsync(instance); // 创建一个测试服务器 var testServer = new TestServer(new WebApplicationFactory().WithWebHostBuilder(builder => { builder.Configure(app => { app.MapDelete("/api/test", () => Results.Ok(expectedResponse)); }); })); // 使用测试服务器的 HttpClient var testHttpClient = testServer.CreateClient(); var testServiceClient = new ServiceClient(_nacosNamingServiceMock.Object, testHttpClient, _loggerMock.Object); // Act var result = await testServiceClient.DeleteAsync(serviceName, endpoint); // Assert Assert.NotNull(result); Assert.Equal(expectedResponse.Message, ((dynamic)result).Message); } } }