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("*已存在*"); } }