166 lines
4.9 KiB
C#
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();
|
|
}
|
|
}
|