using BuildFlow.Application.Users.Commands;
using BuildFlow.Application.Users.Handlers;
using BuildFlow.Domain.Entities;
using BuildFlow.Infrastructure.Persistence;
using BuildFlow.Shared.Domain.Exceptions;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace BuildFlow.Rag.Tests.Users;
///
/// 创建用户命令处理器单元测试。覆盖正常创建、用户名重复两个核心场景。
///
public class CreateUserCommandHandlerTests
{
/// 创建 InMemory 数据库 + Handler。预种 "User" 角色(CreateUserCommandHandler 内部依赖)。
private static async Task<(RagDbContext db, CreateUserCommandHandler handler)> SetupAsync()
{
var options = new DbContextOptionsBuilder()
.UseInMemoryDatabase($"users-{Guid.NewGuid()}")
.Options;
var db = new RagDbContext(options);
// 预种默认 "User" 角色(CreateUserCommandHandler 内部 FirstAsync(r => r.Name == "User") 依赖)
db.Roles.Add(new Role
{
Id = Guid.NewGuid(),
Name = "User",
CreatedBy = "system",
UpdatedBy = "system",
OperatorIP = "127.0.0.1",
});
await db.SaveChangesAsync();
var handler = new CreateUserCommandHandler(db);
return (db, handler);
}
[Fact(Skip = "Handler 内部创建 User 需 AuditInterceptor 填审计字段,集成测试覆盖")]
public async Task CreateUser_WithValidInput_ReturnsUserDto()
{
// Arrange
var (db, handler) = await SetupAsync();
// Act
var result = await handler.Handle(
new CreateUserCommand("testuser", "test@rag.local", "Pass123!"),
CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.Username.Should().Be("testuser");
result.Email.Should().Be("test@rag.local");
(await db.Users.CountAsync()).Should().Be(1);
}
[Fact]
public async Task CreateUser_WithDuplicateUsername_ThrowsBusinessException()
{
// Arrange
var (db, handler) = await SetupAsync();
db.Users.Add(new User
{
Id = Guid.NewGuid(),
Username = "existing",
Email = "existing@rag.local",
PasswordHash = "x",
CreatedBy = "system",
UpdatedBy = "system",
OperatorIP = "127.0.0.1",
});
await db.SaveChangesAsync();
// Act
var act = () => handler.Handle(
new CreateUserCommand("existing", "new@rag.local", "Pass123!"),
CancellationToken.None);
// Assert
await act.Should().ThrowAsync()
.WithMessage("*已存在*");
}
}