using FluentAssertions; using Microsoft.EntityFrameworkCore; using NSubstitute; using Xunit; using BuildFlow.Platform.Application.Users.Commands; using BuildFlow.Platform.Application.Users.Handlers; using BuildFlow.Platform.Domain.Common; using BuildFlow.Shared.Domain.Exceptions; namespace BuildFlow.Platform.Tests.Users; /// /// 分配角色 Command 处理器单元测试。覆盖分配成功 + 权限版本号自增、角色不存在拒绝。 /// public class AssignRolesCommandHandlerTests { [Fact] public async Task Handle_ValidAssignment_ShouldBumpPermissionVersion() { // Arrange var db = PlatformTestDb.CreateDbContext(); var userId = Guid.NewGuid(); await PlatformTestDb.SeedUserAsync(db, userId, "assign-target", permissionVersion: 3); var roleId = Guid.NewGuid(); db.Roles.Add(PlatformTestDb.WithAudit(new BuildFlow.Platform.Domain.Entities.Role { Id = roleId, Name = "Editor" })); await db.SaveChangesAsync(); var versionStore = Substitute.For(); var handler = new AssignRolesCommandHandler(db, versionStore); // Act await handler.Handle(new AssignRolesCommand(userId, [roleId]), CancellationToken.None); // Assert:版本号自增(3 → 4)+ Redis 镜像同步 var user = await db.Users.FirstAsync(u => u.Id == userId); user.PermissionVersion.Should().Be(4); await versionStore.Received(1).BumpAsync(Arg.Is>(ids => ids.Contains(userId)), Arg.Any()); } [Fact] public async Task Handle_NonExistentRole_ShouldThrowNotFound() { // Arrange var db = PlatformTestDb.CreateDbContext(); var userId = Guid.NewGuid(); await PlatformTestDb.SeedUserAsync(db, userId, "victim"); var handler = new AssignRolesCommandHandler(db, Substitute.For()); // Act var act = () => handler.Handle(new AssignRolesCommand(userId, [Guid.NewGuid()]), CancellationToken.None); // Assert await act.Should().ThrowAsync() .WithMessage("*部分角色不存在*"); } }