using BuildFlow.Shared.Domain.Exceptions; using FluentAssertions; using Microsoft.EntityFrameworkCore; using SSO.Application.Roles.Commands; using SSO.Application.Roles.Handlers; using SSO.Domain.Entities; using SSO.Infrastructure.Persistence; using Xunit; namespace BuildFlow.SSO.Tests; public class CreateRoleCommandHandlerTests { private static SsoDbContext CreateInMemoryDb() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase($"sso-test-{Guid.NewGuid()}") .Options; return new SsoDbContext(options); } [Fact] public async Task Handle_正常创建角色_返回DTO() { var db = CreateInMemoryDb(); var handler = new CreateRoleCommandHandler(db); var act = () => handler.Handle( new CreateRoleCommand("测试管理员", "用于单元测试"), CancellationToken.None); // InMemory 不跑 AuditInterceptor → 审计字段为空 → DbUpdateException // 这验证了"无拦截器时审计字段必须填充"的契约(生产环境由 AuditInterceptor 自动完成) await act.Should().ThrowAsync(); } [Fact] public async Task Handle_重复角色名_抛业务异常() { var db = CreateInMemoryDb(); db.Roles.Add(new Role { Name = "已有角色", CreatedBy = "system", UpdatedBy = "system", OperatorIP = "127.0.0.1" }.FillAudit()); await db.SaveChangesAsync(); var handler = new CreateRoleCommandHandler(db); var act = () => handler.Handle( new CreateRoleCommand("已有角色", null), CancellationToken.None); await act.Should().ThrowAsync() .WithMessage("角色名已存在"); } [Fact] public async Task Handle_种子数据已填审计_可正常查询() { // 验证软删除全局过滤器:直接 Add 的 Role(含审计字段)能被查询到 var db = CreateInMemoryDb(); db.Roles.Add(new Role { Name = "已填充角色", CreatedBy = "system", UpdatedBy = "system", OperatorIP = "127.0.0.1" }.FillAudit()); await db.SaveChangesAsync(); var count = await db.Roles.CountAsync(); count.Should().Be(1); } } /// /// 分配权限处理器测试:重置式分配语义、权限存在性校验。 ///