xiangyixiangqin/server/tests/XiangYi.Api.Tests/AppApi/AuthControllerIntegrationTests.cs
2026-01-02 18:00:49 +08:00

204 lines
6.8 KiB
C#

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;
/// <summary>
/// 认证控制器集成测试
/// </summary>
public class AuthControllerIntegrationTests : IClassFixture<WebApplicationFactory<IAppApiMarker>>
{
private readonly WebApplicationFactory<IAppApiMarker> _factory;
private readonly IAuthService _mockAuthService;
public AuthControllerIntegrationTests(WebApplicationFactory<IAppApiMarker> factory)
{
_mockAuthService = Substitute.For<IAuthService>();
_factory = factory.WithWebHostBuilder(builder =>
{
builder.UseEnvironment("Testing");
builder.ConfigureServices(services =>
{
services.RemoveAll<IAuthService>();
services.AddSingleton(_mockAuthService);
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = TestAuthHandler.AuthenticationScheme;
options.DefaultChallengeScheme = TestAuthHandler.AuthenticationScheme;
})
.AddScheme<AuthenticationSchemeOptions, TestAuthHandler>(
TestAuthHandler.AuthenticationScheme, options => { });
});
});
}
/// <summary>
/// 测试微信登录 - 成功场景
/// </summary>
[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<ApiResponse<LoginResponse>>(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);
}
/// <summary>
/// 测试微信登录 - 空code返回错误
/// </summary>
[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<ApiResponse<LoginResponse>>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(30003, result.Code); // MissingParameter
}
/// <summary>
/// 测试绑定手机号 - 未授权返回401
/// </summary>
[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);
}
/// <summary>
/// 测试绑定手机号 - 授权后成功
/// </summary>
[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<ApiResponse<BindPhoneResponse>>(content,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(result);
Assert.Equal(0, result.Code);
Assert.NotNull(result.Data);
Assert.Equal(expectedResponse.Phone, result.Data.Phone);
}
/// <summary>
/// 测试相亲编号格式 - 6位数字且首位不为0
/// </summary>
[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<ApiResponse<LoginResponse>>(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
}
}