vending-machine/backend/tests/VendingMachine.Tests/UserServiceTests.cs
2026-04-03 06:07:13 +08:00

166 lines
4.9 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Moq;
using VendingMachine.Application.DTOs.User;
using VendingMachine.Infrastructure.Data;
using VendingMachine.Infrastructure.Services;
using Xunit;
namespace VendingMachine.Tests;
/// <summary>
/// 用户认证单元测试
/// 需求: 1.1, 1.3, 1.7
/// </summary>
public class UserServiceTests : IDisposable
{
private readonly AppDbContext _db;
private readonly InMemoryVerificationCodeStore _codeStore;
private readonly UserService _userService;
public UserServiceTests()
{
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
_db = new AppDbContext(options);
_codeStore = new InMemoryVerificationCodeStore();
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["Jwt:Secret"] = "TestSecretKeyForUnitTesting_AtLeast32Characters!",
["Jwt:Issuer"] = "Test",
["Jwt:Audience"] = "Test",
["Jwt:ExpirationMinutes"] = "60"
})
.Build();
var logger = new Mock<ILogger<UserService>>();
_userService = new UserService(_db, _codeStore, config, logger.Object);
}
/// <summary>
/// 测试发送验证码成功 - 需求 1.1
/// </summary>
[Fact]
public async Task SendVerificationCode_ValidInput_ShouldSucceed()
{
var result = await _userService.SendVerificationCodeAsync(
new SendCodeRequest { Phone = "912345678", AreaCode = "+886" });
Assert.True(result.Success);
Assert.Single(_codeStore.Store);
}
/// <summary>
/// 测试发送验证码 - 无效区号
/// </summary>
[Fact]
public async Task SendVerificationCode_InvalidAreaCode_ShouldFail()
{
var result = await _userService.SendVerificationCodeAsync(
new SendCodeRequest { Phone = "912345678", AreaCode = "886" });
Assert.False(result.Success);
}
/// <summary>
/// 测试登录成功流程 - 需求 1.3
/// </summary>
[Fact]
public async Task Login_ValidCode_ShouldSucceed()
{
await _userService.SendVerificationCodeAsync(
new SendCodeRequest { Phone = "912345678", AreaCode = "+886" });
var storedCode = _codeStore.Store.Values.First();
var result = await _userService.LoginAsync(new LoginRequest
{
Phone = "912345678",
AreaCode = "+886",
Code = storedCode,
AgreementAccepted = true
});
Assert.True(result.Success);
Assert.NotNull(result.Data);
Assert.NotEmpty(result.Data!.Token);
Assert.Equal("912345678", result.Data.UserInfo.Phone);
}
/// <summary>
/// 测试登录失败 - 验证码错误 - 需求 1.3
/// </summary>
[Fact]
public async Task Login_WrongCode_ShouldFail()
{
await _userService.SendVerificationCodeAsync(
new SendCodeRequest { Phone = "912345678", AreaCode = "+886" });
var result = await _userService.LoginAsync(new LoginRequest
{
Phone = "912345678",
AreaCode = "+886",
Code = "000000",
AgreementAccepted = true
});
Assert.False(result.Success);
Assert.Contains("验证码", result.Message);
}
/// <summary>
/// 测试登录失败 - 未勾选协议
/// </summary>
[Fact]
public async Task Login_AgreementNotAccepted_ShouldFail()
{
var result = await _userService.LoginAsync(new LoginRequest
{
Phone = "912345678",
AreaCode = "+886",
Code = "123456",
AgreementAccepted = false
});
Assert.False(result.Success);
Assert.Contains("协议", result.Message);
}
/// <summary>
/// 测试注销账号流程 - 需求 1.7
/// </summary>
[Fact]
public async Task DeleteAccount_ExistingUser_ShouldSoftDelete()
{
await _userService.SendVerificationCodeAsync(
new SendCodeRequest { Phone = "912345678", AreaCode = "+886" });
var storedCode = _codeStore.Store.Values.First();
var loginResult = await _userService.LoginAsync(new LoginRequest
{
Phone = "912345678",
AreaCode = "+886",
Code = storedCode,
AgreementAccepted = true
});
var uid = loginResult.Data!.UserInfo.Uid;
var deleteResult = await _userService.DeleteAccountAsync(uid);
Assert.True(deleteResult.Success);
Assert.Contains("已注销", deleteResult.Message);
// 注销后应无法获取用户信息
var infoResult = await _userService.GetUserInfoAsync(uid);
Assert.False(infoResult.Success);
}
public void Dispose()
{
_db.Dispose();
}
}