build-flow.api/tests/BuildFlow.Scripting.Tests/ScriptCommandHandlerTests.cs
xiangning 6c110b579a refactor(dependencies): 移除未使用的域实体引用
- 从文件模块的多部分上传处理器中移除未使用的实体引用
- 从即时通讯模块的群组成员处理器中移除未使用的实体引用
- 从RAG模块的AI模型配置中移除未使用的实体引用
- 从监控模块的告警规则配置中移除未使用的实体引用
- 从平台模块的角色权限处理器中移除未使用的实体引用
- 从脚本模块的执行日志实体引用中进行清理
- 从多个基础设施配置类中移除未使用的依赖项
- 优化测试文件中的导入声明,移除不必要的引用
2026-07-19 14:09:47 +08:00

185 lines
7.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using BuildFlow.Shared.Domain.Exceptions;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Scripting.Application.Commands;
using Scripting.Application.Handlers;
using Scripting.Domain.Entities.ScriptFunction;
using Scripting.Domain.Enums;
using Scripting.Infrastructure.Persistence;
using Xunit;
namespace BuildFlow.Scripting.Tests;
/// <summary>
/// 脚本 CQRS 命令处理器测试(spec §13 #6 可编辑性、生命周期守卫)。
/// 用真实 InMemory ScriptingDbContext 直接实例化 handler,覆盖:
/// Create(唯一名校验 + 默认超时)、Update(Disabled 拒绝 + Published 自增版本)、
/// Delete(Published 拒绝 + Draft 软删除)、Publish(状态 + 版本)。
/// </summary>
public class ScriptCommandHandlerTests
{
// ── Create ─────────────────────────────────────────────────────────────
[Fact]
public async Task CreateScript_DuplicateName_ThrowsBusinessException()
{
await using var db = ScriptingTestDbFactory.Create();
await SeedAsync(db, name: "dup-fn");
var handler = new CreateScriptCommandHandler(db);
var act = () => handler.Handle(
new CreateScriptCommand("dup-fn", "显示名", null, "return 1;", null, null, 0),
CancellationToken.None);
await act.Should().ThrowAsync<BusinessException>().WithMessage("*已存在*");
}
[Fact]
public async Task CreateScript_DefaultsTimeoutTo5000()
{
await using var db = ScriptingTestDbFactory.Create();
var handler = new CreateScriptCommandHandler(db);
var dto = await handler.Handle(
new CreateScriptCommand("default-timeout", "默认超时", null, "return 1;", null, null, 0),
CancellationToken.None);
dto.TimeoutMs.Should().Be(5000);
dto.Status.Should().Be(ScriptStatusEnum.Draft);
dto.Version.Should().Be(1);
var entity = await db.Scripts.FindAsync(dto.Id);
entity.Should().NotBeNull();
entity!.TimeoutMs.Should().Be(5000);
}
[Fact]
public async Task CreateScript_NewName_PersistsEntity()
{
await using var db = ScriptingTestDbFactory.Create();
var handler = new CreateScriptCommandHandler(db);
var dto = await handler.Handle(
new CreateScriptCommand("unique-fn", "唯一函数", "desc", "return 42;", null, null, 3000),
CancellationToken.None);
dto.Name.Should().Be("unique-fn");
dto.Code.Should().Be("return 42;");
dto.TimeoutMs.Should().Be(3000);
}
// ── Update ─────────────────────────────────────────────────────────────
[Fact]
public async Task UpdateScript_DisabledScript_Throws()
{
await using var db = ScriptingTestDbFactory.Create();
var script = await SeedAsync(db, name: "disabled-fn", status: ScriptStatusEnum.Disabled);
var handler = new UpdateScriptCommandHandler(db);
var act = () => handler.Handle(
new UpdateScriptCommand(script.Id, "新名", null, "return 2;", null, null, 5000),
CancellationToken.None);
await act.Should().ThrowAsync<BusinessException>().WithMessage("*不能编辑*");
}
[Fact]
public async Task UpdateScript_Published_IncrementsVersion()
{
await using var db = ScriptingTestDbFactory.Create();
var script = await SeedAsync(db, name: "pub-fn", status: ScriptStatusEnum.Published, version: 3);
var handler = new UpdateScriptCommandHandler(db);
var dto = await handler.Handle(
new UpdateScriptCommand(script.Id, "改后", null, "return 99;", null, null, 5000),
CancellationToken.None);
dto.Version.Should().Be(4);
dto.DisplayName.Should().Be("改后");
dto.Code.Should().Be("return 99;");
dto.Status.Should().Be(ScriptStatusEnum.Published); // 保持已发布
}
[Fact]
public async Task UpdateScript_Draft_KeepsVersionAtOne()
{
await using var db = ScriptingTestDbFactory.Create();
var script = await SeedAsync(db, name: "draft-fn", status: ScriptStatusEnum.Draft);
var handler = new UpdateScriptCommandHandler(db);
var dto = await handler.Handle(
new UpdateScriptCommand(script.Id, "草稿改", null, "return 1;", null, null, 5000),
CancellationToken.None);
dto.Version.Should().Be(1); // 草稿编辑不递增版本
}
// ── Delete ─────────────────────────────────────────────────────────────
[Fact]
public async Task DeleteScript_Published_Throws()
{
await using var db = ScriptingTestDbFactory.Create();
var script = await SeedAsync(db, name: "del-pub", status: ScriptStatusEnum.Published);
var handler = new DeleteScriptCommandHandler(db);
var act = () => handler.Handle(new DeleteScriptCommand(script.Id), CancellationToken.None);
await act.Should().ThrowAsync<BusinessException>().WithMessage("*不能删除*");
}
[Fact]
public async Task DeleteScript_Draft_SoftDeletes()
{
await using var db = ScriptingTestDbFactory.Create();
var script = await SeedAsync(db, name: "del-draft", status: ScriptStatusEnum.Draft);
var handler = new DeleteScriptCommandHandler(db);
await handler.Handle(new DeleteScriptCommand(script.Id), CancellationToken.None);
var entity = await db.Scripts.IgnoreQueryFilters().FirstAsync(x => x.Id == script.Id);
entity.IsDeleted.Should().BeTrue();
}
// ── Publish ────────────────────────────────────────────────────────────
[Fact]
public async Task PublishScript_SetsPublishedAndIncrementsVersion()
{
await using var db = ScriptingTestDbFactory.Create();
var script = await SeedAsync(db, name: "to-publish", status: ScriptStatusEnum.Draft, version: 1);
var handler = new PublishScriptCommandHandler(db);
var dto = await handler.Handle(new PublishScriptCommand(script.Id), CancellationToken.None);
dto.Status.Should().Be(ScriptStatusEnum.Published);
dto.Version.Should().Be(2);
}
// ── 夹具 ───────────────────────────────────────────────────────────────
private static async Task<ScriptFunctionEntity> SeedAsync(
ScriptingDbContext db,
string name,
ScriptStatusEnum status = ScriptStatusEnum.Draft,
int version = 1)
{
var script = new ScriptFunctionEntity
{
Id = Guid.NewGuid(),
Name = name,
DisplayName = name,
Code = "return 1;",
Status = status,
Version = version,
TimeoutMs = 5000,
CreatedBy = "test",
UpdatedBy = "test",
OperatorIP = "127.0.0.1",
};
db.Scripts.Add(script);
await db.SaveChangesAsync();
return script;
}
}