Files
EmailBill/WebApi.Test/Application/AuthApplicationTest.cs

153 lines
4.3 KiB
C#
Raw Normal View History

2026-02-10 17:49:19 +08:00
using Service.AppSettingModel;
namespace WebApi.Test.Application;
/// <summary>
/// AuthApplication 单元测试
/// </summary>
public class AuthApplicationTest : BaseApplicationTest
{
private readonly AuthSettings _authSettings;
private readonly JwtSettings _jwtSettings;
private readonly ILogger<AuthApplication> _logger;
private readonly AuthApplication _application;
public AuthApplicationTest()
{
// 配置测试用的设置
_authSettings = new AuthSettings { Password = "test-password-123" };
_jwtSettings = new JwtSettings
{
SecretKey = "test-secret-key-minimum-32-characters-long-for-hmacsha256",
Issuer = "TestIssuer",
Audience = "TestAudience",
ExpirationHours = 24
};
var authOptions = Options.Create(_authSettings);
var jwtOptions = Options.Create(_jwtSettings);
_logger = CreateMockLogger<AuthApplication>();
_application = new AuthApplication(authOptions, jwtOptions, _logger);
}
#region Login Tests
[Fact]
public void Login_有效密码_应返回Token和过期时间()
{
// Arrange
var request = new LoginRequest { Password = "test-password-123" };
// Act
var response = _application.Login(request);
// Assert
response.Should().NotBeNull();
response.Token.Should().NotBeEmpty();
response.ExpiresAt.Should().BeAfter(DateTime.UtcNow);
response.ExpiresAt.Should().BeOnOrBefore(DateTime.UtcNow.AddHours(25)); // 允许1小时误差
}
[Fact]
public void Login_空密码_应抛出ValidationException()
{
// Arrange
var request = new LoginRequest { Password = "" };
// Act & Assert
var exception = Assert.Throws<ValidationException>(() => _application.Login(request));
exception.Message.Should().Contain("密码不能为空");
}
[Fact]
public void Login_错误密码_应抛出ValidationException()
{
// Arrange
var request = new LoginRequest { Password = "wrong-password" };
// Act & Assert
var exception = Assert.Throws<ValidationException>(() => _application.Login(request));
exception.Message.Should().Contain("密码错误");
}
[Fact]
public void Login_多次调用_应生成不同Token()
{
// Arrange
var request = new LoginRequest { Password = "test-password-123" };
// Act
var response1 = _application.Login(request);
System.Threading.Thread.Sleep(10); // 确保时间戳不同
var response2 = _application.Login(request);
// Assert
response1.Token.Should().NotBe(response2.Token);
}
[Fact]
public void Login_生成的Token_应为有效JWT格式()
{
// Arrange
var request = new LoginRequest { Password = "test-password-123" };
// Act
var response = _application.Login(request);
// Assert
response.Token.Should().NotBeEmpty();
var parts = response.Token.Split('.');
parts.Should().HaveCount(3); // JWT格式: header.payload.signature
}
[Fact]
public void Login_成功登录_应记录日志()
{
// Arrange
var request = new LoginRequest { Password = "test-password-123" };
// Act
_application.Login(request);
// Assert
// 验证LogInformation被调用过
_logger.Received().Log(
LogLevel.Information,
Arg.Any<EventId>(),
Arg.Is<object>(o => o.ToString()!.Contains("登录成功")),
Arg.Any<Exception>(),
Arg.Any<Func<object, Exception?, string>>()!
);
}
[Fact]
public void Login_密码错误_应记录警告日志()
{
// Arrange
var request = new LoginRequest { Password = "wrong-password" };
// Act
try
{
_application.Login(request);
}
catch (ValidationException)
{
// 预期异常
}
// Assert
// 验证LogWarning被调用过
_logger.Received().Log(
LogLevel.Warning,
Arg.Any<EventId>(),
Arg.Is<object>(o => o.ToString()!.Contains("密码错误")),
Arg.Any<Exception>(),
Arg.Any<Func<object, Exception?, string>>()!
);
}
#endregion
}