xiangning 51eea796e2 refactor(rag): 重构AI模型相关代码结构和数据库迁移逻辑
- 将AI模型相关端点、命令、处理器移动到模块内部统一管理
- 优化数据库迁移脚本,添加对不同环境表状态的兼容处理逻辑
- 为异常处理添加错误码枚举参数,统一错误处理方式
- 重构多处业务逻辑中的异常抛出方式,增强代码一致性
- 移除独立的组件清单分组和项目定义,简化前端物料面板数据结构
- 修复测试代码中实体引用路径错误问题
- 添加新的监控模块测试项目到解决方案文件中
2026-07-20 08:25:18 +08:00

171 lines
6.6 KiB
C#

using BuildFlow.Platform.Domain.Entities.Permission;
using BuildFlow.Platform.Application.Permissions.Commands;
using BuildFlow.Platform.Application.Permissions.Handlers;
using BuildFlow.Platform.Application.Permissions.Queries;
using BuildFlow.Platform.Domain.Entities.Role;
using BuildFlow.Platform.Domain.Entities.RolePermission;
using BuildFlow.Platform.Infrastructure.Persistence;
using BuildFlow.Shared.Domain.Exceptions;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace BuildFlow.Platform.Tests.Permissions;
/// <summary>
/// [SOP-PLATFORM] 权限管理全 Handler 覆盖测试。
/// 覆盖: Create / Update / Delete / GetList / GetById / GetTree。
/// 飞书矩阵: platform/Permissions 子域(6 Handler 零覆盖→全补)
/// </summary>
public class PermissionHandlerTests
{
private static PlatformDbContext CreateDb([System.Runtime.CompilerServices.CallerMemberName] string name = "")
=> PlatformTestDb.CreateDbContext(name);
private static PermissionEntity NewPermission(string code, string? group = "TestGroup")
=> PlatformTestDb.WithAudit(new PermissionEntity
{
Name = $"权限_{code}",
Code = code,
Description = "desc",
Group = group
});
[Fact]
public async Task Create_Valid_ReturnsDto()
{
var db = CreateDb();
var handler = new CreatePermissionCommandHandler(db);
var result = await handler.Handle(
new CreatePermissionCommand("创建用户", "user:create", "描述", "UserManagement"),
CancellationToken.None);
result.Code.Should().Be("user:create");
result.Name.Should().Be("创建用户");
(await db.Permissions.CountAsync()).Should().Be(1);
}
[Fact]
public async Task Create_DuplicateCode_ThrowsBusiness()
{
var db = CreateDb();
db.Permissions.Add(NewPermission("user:create"));
await db.SaveChangesAsync();
var handler = new CreatePermissionCommandHandler(db);
var act = async () => await handler.Handle(
new CreatePermissionCommand("重复", "user:create", null, null), CancellationToken.None);
await act.Should().ThrowAsync<BusinessException>("Code 唯一,重复应拒绝");
}
[Fact]
public async Task Update_Existing_OverwritesNullableFields()
{
var db = CreateDb();
var p = NewPermission("user:read");
db.Permissions.Add(p);
await db.SaveChangesAsync();
var handler = new UpdatePermissionCommandHandler(db);
var result = await handler.Handle(
new UpdatePermissionCommand(p.Id, "新名称", "新描述", "NewGroup"), CancellationToken.None);
result.Name.Should().Be("新名称");
result.Description.Should().Be("新描述");
result.Group.Should().Be("NewGroup");
result.Code.Should().Be("user:read", "Code 不可改");
}
[Fact]
public async Task Update_NonExistent_ThrowsNotFound()
{
var db = CreateDb();
var handler = new UpdatePermissionCommandHandler(db);
var act = async () => await handler.Handle(
new UpdatePermissionCommand(Guid.NewGuid(), "x", null, null), CancellationToken.None);
await act.Should().ThrowAsync<NotFoundException>();
}
[Fact]
public async Task Delete_Existing_RemovesAndUnlinksRoles()
{
var db = CreateDb();
var p = NewPermission("user:delete");
var role = PlatformTestDb.WithAudit(new RoleEntity { Name = "Admin" });
var link = new RolePermissionEntity { Role = role, Permission = p };
db.Roles.Add(role);
db.Permissions.Add(p);
db.RolePermissions.Add(link);
await db.SaveChangesAsync();
var handler = new DeletePermissionCommandHandler(db);
await handler.Handle(new DeletePermissionCommand(p.Id), CancellationToken.None);
(await db.Permissions.AnyAsync(x => x.Id == p.Id)).Should().BeFalse("软删后不可见");
(await db.RolePermissions.AnyAsync(rp => rp.PermissionId == p.Id)).Should().BeFalse("关联应已解除");
}
[Fact]
public async Task Delete_NonExistent_ThrowsNotFound()
{
var db = CreateDb();
var handler = new DeletePermissionCommandHandler(db);
var act = async () => await handler.Handle(new DeletePermissionCommand(Guid.NewGuid()), CancellationToken.None);
await act.Should().ThrowAsync<NotFoundException>();
}
[Fact]
public async Task GetList_ReturnsAll()
{
var db = CreateDb();
db.Permissions.AddRange(NewPermission("p1"), NewPermission("p2"));
await db.SaveChangesAsync();
var handler = new GetPermissionListQueryHandler(db);
var result = await handler.Handle(new GetPermissionListQuery(), CancellationToken.None);
result.Should().HaveCount(2);
}
[Fact]
public async Task GetById_Existing_ReturnsDto()
{
var db = CreateDb();
var p = NewPermission("user:read");
db.Permissions.Add(p);
await db.SaveChangesAsync();
var handler = new GetPermissionByIdQueryHandler(db);
var result = await handler.Handle(new GetPermissionByIdQuery(p.Id), CancellationToken.None);
result.Code.Should().Be("user:read");
}
[Fact]
public async Task GetById_NonExistent_ThrowsNotFound()
{
var db = CreateDb();
var handler = new GetPermissionByIdQueryHandler(db);
var act = async () => await handler.Handle(new GetPermissionByIdQuery(Guid.NewGuid()), CancellationToken.None);
await act.Should().ThrowAsync<NotFoundException>();
}
[Fact]
public async Task GetTree_GroupsByGroupField()
{
var db = CreateDb();
db.Permissions.AddRange(
NewPermission("a:1", "GroupA"),
NewPermission("a:2", "GroupA"),
NewPermission("b:1", "GroupB"));
await db.SaveChangesAsync();
var handler = new GetPermissionTreeQueryHandler(db);
var tree = await handler.Handle(new GetPermissionTreeQuery(), CancellationToken.None);
tree.Should().HaveCount(2);
tree.First(g => g.Group == "GroupA").Permissions.Should().HaveCount(2);
tree.First(g => g.Group == "GroupB").Permissions.Should().HaveCount(1);
}
[Fact]
public async Task GetTree_NullGroup_GoesToUngrouped()
{
var db = CreateDb();
db.Permissions.Add(NewPermission("no:group", null));
await db.SaveChangesAsync();
var handler = new GetPermissionTreeQueryHandler(db);
var tree = await handler.Handle(new GetPermissionTreeQuery(), CancellationToken.None);
tree.Should().ContainSingle();
tree[0].Group.Should().Be("未分组");
}
}