using System.Net; using System.Net.Http.Json; using System.Text.Json; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using NSubstitute; using Xunit; using XiangYi.AppApi; using XiangYi.Application.DTOs.Requests; using XiangYi.Application.DTOs.Responses; using XiangYi.Application.Interfaces; namespace XiangYi.Api.Tests.AppApi; /// /// 认证控制器集成测试 /// public class AuthControllerIntegrationTests : IClassFixture> { private readonly WebApplicationFactory _factory; private readonly IAuthService _mockAuthService; public AuthControllerIntegrationTests(WebApplicationFactory factory) { _mockAuthService = Substitute.For(); _factory = factory.WithWebHostBuilder(builder => { builder.UseEnvironment("Testing"); builder.ConfigureServices(services => { services.RemoveAll(); services.AddSingleton(_mockAuthService); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = TestAuthHandler.AuthenticationScheme; options.DefaultChallengeScheme = TestAuthHandler.AuthenticationScheme; }) .AddScheme( TestAuthHandler.AuthenticationScheme, options => { }); }); }); } /// /// 测试微信登录 - 成功场景 /// [Fact] public async Task Login_WithValidCode_ReturnsSuccess() { // Arrange var expectedResponse = new LoginResponse { Token = "jwt-token-123", UserId = 1, Nickname = "测试用户", XiangQinNo = "123456", IsProfileCompleted = false, IsMember = false, MemberLevel = 0, IsRealName = false, IsNewUser = true }; _mockAuthService.LoginAsync("valid-code") .Returns(Task.FromResult(expectedResponse)); var client = _factory.CreateClient(); var request = new LoginRequest { Code = "valid-code" }; // Act var response = await client.PostAsJsonAsync("/api/app/auth/login", request); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result); Assert.Equal(0, result.Code); Assert.NotNull(result.Data); Assert.Equal(expectedResponse.UserId, result.Data.UserId); Assert.Equal(expectedResponse.XiangQinNo, result.Data.XiangQinNo); } /// /// 测试微信登录 - 空code返回错误 /// [Fact] public async Task Login_WithEmptyCode_ReturnsError() { // Arrange var client = _factory.CreateClient(); var request = new LoginRequest { Code = "" }; // Act var response = await client.PostAsJsonAsync("/api/app/auth/login", request); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result); Assert.Equal(30003, result.Code); // MissingParameter } /// /// 测试绑定手机号 - 未授权返回401 /// [Fact] public async Task BindPhone_WithoutAuth_ReturnsUnauthorized() { // Arrange var client = _factory.CreateClient(); var request = new BindPhoneRequest { Code = "phone-code" }; // Act var response = await client.PostAsJsonAsync("/api/app/auth/bindPhone", request); // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } /// /// 测试绑定手机号 - 授权后成功 /// [Fact] public async Task BindPhone_WithAuth_ReturnsSuccess() { // Arrange var expectedResponse = new BindPhoneResponse { Phone = "138****8888" }; _mockAuthService.BindPhoneAsync(1, "phone-code") .Returns(Task.FromResult(expectedResponse)); var client = _factory.CreateClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer test-token-1"); var request = new BindPhoneRequest { Code = "phone-code" }; // Act var response = await client.PostAsJsonAsync("/api/app/auth/bindPhone", request); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result); Assert.Equal(0, result.Code); Assert.NotNull(result.Data); Assert.Equal(expectedResponse.Phone, result.Data.Phone); } /// /// 测试相亲编号格式 - 6位数字且首位不为0 /// [Fact] public async Task Login_XiangQinNo_ShouldBe6DigitsAndNotStartWithZero() { // Arrange var expectedResponse = new LoginResponse { Token = "jwt-token-123", UserId = 1, XiangQinNo = "123456", IsNewUser = true }; _mockAuthService.LoginAsync("test-code") .Returns(Task.FromResult(expectedResponse)); var client = _factory.CreateClient(); var request = new LoginRequest { Code = "test-code" }; // Act var response = await client.PostAsJsonAsync("/api/app/auth/login", request); // Assert var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize>(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); Assert.NotNull(result?.Data?.XiangQinNo); var xiangQinNo = result.Data.XiangQinNo; // 验证6位数字 Assert.Equal(6, xiangQinNo.Length); Assert.True(xiangQinNo.All(char.IsDigit), "相亲编号应全为数字"); Assert.NotEqual('0', xiangQinNo[0]); // 首位不为0 } }