665 lines
24 KiB
C#
665 lines
24 KiB
C#
using FluentAssertions;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Workflow.Application.Form.DTOs;
|
||
using Workflow.Application.Form.FormDefinition.Commands;
|
||
using Workflow.Application.Form.FormDefinition.Queries;
|
||
using Workflow.Domain.Enums;
|
||
using Workflow.Domain.Exceptions;
|
||
using Workflow.Infrastructure.Persistence;
|
||
using Xunit;
|
||
|
||
namespace Workflow.Tests.Form;
|
||
|
||
[Collection("FormTests")]
|
||
public class FormDefinitionTests
|
||
{
|
||
private readonly FormTestFixture _fixture;
|
||
|
||
public FormDefinitionTests(FormTestFixtureClassFixture fixture)
|
||
{
|
||
_fixture = fixture;
|
||
}
|
||
|
||
// ====================================================================
|
||
// CreateFormDefinition
|
||
// ====================================================================
|
||
|
||
[Fact]
|
||
public async Task CreateFormDefinition_WithValidData_ReturnsDto()
|
||
{
|
||
// Arrange
|
||
await using var db = _fixture.CreateDbContext();
|
||
var handler = new CreateFormDefinitionCommandHandler(db);
|
||
var command = new CreateFormDefinitionCommand(
|
||
Name: "员工入职登记表",
|
||
Code: "EMP_ONBOARD",
|
||
Description: "新员工入职时填写的登记表单",
|
||
Fields: new List<FormFieldDto>
|
||
{
|
||
new(FieldKey: "name", Label: "姓名", FieldType: FieldType.Input, Required: true, DefaultValue: null, Config: "{}", SortOrder: 0),
|
||
new(FieldKey: "department", Label: "部门", FieldType: FieldType.Select, Required: true, DefaultValue: null, Config: """{"options":["研发部","市场部","行政部"]}""", SortOrder: 1),
|
||
new(FieldKey: "entry_date", Label: "入职日期", FieldType: FieldType.Date, Required: true, DefaultValue: null, Config: "{}", SortOrder: 2),
|
||
}
|
||
);
|
||
|
||
// Act
|
||
var result = await handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert
|
||
result.Should().NotBeNull();
|
||
result.Name.Should().Be("员工入职登记表");
|
||
result.Code.Should().Be("EMP_ONBOARD");
|
||
result.Description.Should().Be("新员工入职时填写的登记表单");
|
||
result.Version.Should().Be(1);
|
||
result.Status.Should().Be(FormStatus.Draft);
|
||
|
||
// 验证持久化
|
||
var entity = await db.FormDefinitions.FirstAsync();
|
||
entity.Name.Should().Be("员工入职登记表");
|
||
entity.Code.Should().Be("EMP_ONBOARD");
|
||
}
|
||
|
||
[Fact]
|
||
public async Task CreateFormDefinition_WithDuplicateCode_ThrowsBusinessException()
|
||
{
|
||
// Arrange
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(CreateFormDefinition_WithDuplicateCode_ThrowsBusinessException),
|
||
seedAction: db =>
|
||
{
|
||
db.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
Name = "已存在的表单",
|
||
Code = "DUPLICATE_CODE",
|
||
Version = 1,
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
});
|
||
});
|
||
|
||
var handler = new CreateFormDefinitionCommandHandler(db);
|
||
var command = new CreateFormDefinitionCommand(
|
||
Name: "新表单",
|
||
Code: "DUPLICATE_CODE",
|
||
Description: "尝试使用重复编码",
|
||
Fields: []
|
||
);
|
||
|
||
// Act
|
||
var act = () => handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert
|
||
await act.Should().ThrowAsync<BusinessException>()
|
||
.WithMessage("*编码*已存在*");
|
||
}
|
||
|
||
// ====================================================================
|
||
// UpdateFormDefinition
|
||
// ====================================================================
|
||
|
||
[Fact]
|
||
public async Task UpdateFormDefinition_UpdatesNameAndDescription()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(UpdateFormDefinition_UpdatesNameAndDescription),
|
||
seedAction: db =>
|
||
{
|
||
db.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "旧名称",
|
||
Code = "FORM_001",
|
||
Version = 1,
|
||
Description = "旧描述",
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
});
|
||
});
|
||
|
||
var handler = new UpdateFormDefinitionCommandHandler(db);
|
||
var command = new UpdateFormDefinitionCommand(
|
||
Id: formId,
|
||
Name: "新名称",
|
||
Description: "新描述",
|
||
Fields: []
|
||
);
|
||
|
||
// Act
|
||
var result = await handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert
|
||
result.Should().NotBeNull();
|
||
result.Name.Should().Be("新名称");
|
||
result.Description.Should().Be("新描述");
|
||
|
||
// 验证持久化
|
||
var entity = await db.FormDefinitions.FindAsync(formId);
|
||
entity.Should().NotBeNull();
|
||
entity!.Name.Should().Be("新名称");
|
||
entity.Description.Should().Be("新描述");
|
||
// Code 不应被修改
|
||
entity.Code.Should().Be("FORM_001");
|
||
}
|
||
|
||
[Fact]
|
||
public async Task UpdateFormDefinition_AddsFieldsToForm()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(UpdateFormDefinition_AddsFieldsToForm),
|
||
seedAction: db =>
|
||
{
|
||
db.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "表单",
|
||
Code = "FORM_ADD_FIELDS",
|
||
Version = 1,
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
});
|
||
});
|
||
|
||
var handler = new UpdateFormDefinitionCommandHandler(db);
|
||
var command = new UpdateFormDefinitionCommand(
|
||
Id: formId,
|
||
Name: "表单",
|
||
Description: null,
|
||
Fields: new List<FormFieldDto>
|
||
{
|
||
new(FieldKey: "email", Label: "邮箱", FieldType: FieldType.Input, Required: false, DefaultValue: null, Config: "{}", SortOrder: 0),
|
||
new(FieldKey: "phone", Label: "电话", FieldType: FieldType.Input, Required: true, DefaultValue: null, Config: "{}", SortOrder: 1),
|
||
}
|
||
);
|
||
|
||
// Act
|
||
await handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert
|
||
var form = await db.FormDefinitions
|
||
.Include(f => f.Fields)
|
||
.FirstAsync(f => f.Id == formId);
|
||
|
||
form.Fields.Should().HaveCount(2);
|
||
form.Fields.Select(f => f.FieldKey).Should().Contain(["email", "phone"]);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task UpdateFormDefinition_RemovesFieldsFromForm()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
var fieldId1 = Guid.NewGuid();
|
||
var fieldId2 = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(UpdateFormDefinition_RemovesFieldsFromForm),
|
||
seedAction: db =>
|
||
{
|
||
var form = new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "表单",
|
||
Code = "FORM_REM_FIELDS",
|
||
Version = 1,
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
};
|
||
form.Fields.Add(new Domain.Entities.FormDefinitionField
|
||
{
|
||
Id = fieldId1,
|
||
FormDefinitionId = formId,
|
||
FieldKey = "keep_me",
|
||
Label = "保留字段",
|
||
FieldType = FieldType.Input,
|
||
Required = false,
|
||
Config = "{}",
|
||
SortOrder = 0,
|
||
});
|
||
form.Fields.Add(new Domain.Entities.FormDefinitionField
|
||
{
|
||
Id = fieldId2,
|
||
FormDefinitionId = formId,
|
||
FieldKey = "remove_me",
|
||
Label = "删除字段",
|
||
FieldType = FieldType.Input,
|
||
Required = false,
|
||
Config = "{}",
|
||
SortOrder = 1,
|
||
});
|
||
db.FormDefinitions.Add(form);
|
||
});
|
||
|
||
var handler = new UpdateFormDefinitionCommandHandler(db);
|
||
// 只传保留的字段,remove_me 不在列表中
|
||
var command = new UpdateFormDefinitionCommand(
|
||
Id: formId,
|
||
Name: "表单",
|
||
Description: null,
|
||
Fields: new List<FormFieldDto>
|
||
{
|
||
new(FieldKey: "keep_me", Label: "保留字段", FieldType: FieldType.Input, Required: false, DefaultValue: null, Config: "{}", SortOrder: 0),
|
||
}
|
||
);
|
||
|
||
// Act
|
||
await handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert
|
||
var form = await db.FormDefinitions
|
||
.Include(f => f.Fields)
|
||
.FirstAsync(f => f.Id == formId);
|
||
|
||
form.Fields.Should().HaveCount(1);
|
||
form.Fields[0].FieldKey.Should().Be("keep_me");
|
||
}
|
||
|
||
[Fact]
|
||
public async Task UpdateFormDefinition_ModifiesFieldProperties()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(UpdateFormDefinition_ModifiesFieldProperties),
|
||
seedAction: db =>
|
||
{
|
||
var form = new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "表单",
|
||
Code = "FORM_MOD_FIELDS",
|
||
Version = 1,
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
};
|
||
form.Fields.Add(new Domain.Entities.FormDefinitionField
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
FormDefinitionId = formId,
|
||
FieldKey = "age",
|
||
Label = "年龄",
|
||
FieldType = FieldType.Input,
|
||
Required = false,
|
||
Config = "{}",
|
||
SortOrder = 0,
|
||
});
|
||
db.FormDefinitions.Add(form);
|
||
});
|
||
|
||
var handler = new UpdateFormDefinitionCommandHandler(db);
|
||
// 修改字段:从 Input 改为 Number,从非必填改为必填,标签从 "年龄" 改为 "用户年龄"
|
||
var command = new UpdateFormDefinitionCommand(
|
||
Id: formId,
|
||
Name: "表单",
|
||
Description: null,
|
||
Fields: new List<FormFieldDto>
|
||
{
|
||
new(FieldKey: "age", Label: "用户年龄", FieldType: FieldType.Number, Required: true, DefaultValue: "18", Config: """{"min":0,"max":150}""", SortOrder: 0),
|
||
}
|
||
);
|
||
|
||
// Act
|
||
await handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert
|
||
var form = await db.FormDefinitions
|
||
.Include(f => f.Fields)
|
||
.FirstAsync(f => f.Id == formId);
|
||
|
||
form.Fields.Should().HaveCount(1);
|
||
var field = form.Fields[0];
|
||
field.Label.Should().Be("用户年龄");
|
||
field.FieldType.Should().Be(FieldType.Number);
|
||
field.Required.Should().BeTrue();
|
||
field.DefaultValue.Should().Be("18");
|
||
field.Config.Should().Contain("min");
|
||
}
|
||
|
||
// ====================================================================
|
||
// DeleteFormDefinition (soft delete)
|
||
// ====================================================================
|
||
|
||
[Fact]
|
||
public async Task DeleteFormDefinition_SetsIsDeletedTrue()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(DeleteFormDefinition_SetsIsDeletedTrue),
|
||
seedAction: ctx =>
|
||
{
|
||
ctx.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "待删除表单",
|
||
Code = "DEL_FORM",
|
||
Version = 1,
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
});
|
||
});
|
||
|
||
var handler = new DeleteFormDefinitionCommandHandler(db);
|
||
var command = new DeleteFormDefinitionCommand(Id: formId);
|
||
|
||
// Act
|
||
await handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert — 软删除后通过默认查询应找不到
|
||
var normalQuery = await db.FormDefinitions.FindAsync(formId);
|
||
normalQuery.Should().BeNull();
|
||
|
||
// 通过 IgnoreQueryFilters 可以找到,且 IsDeleted = true
|
||
var deletedEntity = await db.FormDefinitions
|
||
.IgnoreQueryFilters()
|
||
.FirstAsync(f => f.Id == formId);
|
||
deletedEntity.IsDeleted.Should().BeTrue();
|
||
}
|
||
|
||
[Fact]
|
||
public async Task DeleteFormDefinition_DoesNotHardDelete()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(DeleteFormDefinition_DoesNotHardDelete),
|
||
seedAction: ctx =>
|
||
{
|
||
ctx.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "待删除表单",
|
||
Code = "NO_HARD_DEL",
|
||
Version = 1,
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
});
|
||
});
|
||
|
||
var handler = new DeleteFormDefinitionCommandHandler(db);
|
||
var command = new DeleteFormDefinitionCommand(Id: formId);
|
||
|
||
// Act
|
||
await handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert — 物理记录仍然存在于数据库中
|
||
var records = await db.FormDefinitions.IgnoreQueryFilters().CountAsync(f => f.Id == formId);
|
||
records.Should().Be(1);
|
||
}
|
||
|
||
// ====================================================================
|
||
// PublishFormDefinition
|
||
// ====================================================================
|
||
|
||
[Fact]
|
||
public async Task PublishFormDefinition_ChangesStatusFromDraftToPublished()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(PublishFormDefinition_ChangesStatusFromDraftToPublished),
|
||
seedAction: ctx =>
|
||
{
|
||
ctx.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "待发布表单",
|
||
Code = "PUB_FORM",
|
||
Version = 1,
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
});
|
||
});
|
||
|
||
var handler = new PublishFormDefinitionCommandHandler(db);
|
||
var command = new PublishFormDefinitionCommand(Id: formId);
|
||
|
||
// Act
|
||
await handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert
|
||
var entity = await db.FormDefinitions.FindAsync(formId);
|
||
entity.Should().NotBeNull();
|
||
entity!.Status.Should().Be(FormStatus.Published);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task PublishFormDefinition_AlreadyPublished_ThrowsBusinessException()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(PublishFormDefinition_AlreadyPublished_ThrowsBusinessException),
|
||
seedAction: ctx =>
|
||
{
|
||
ctx.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "已发布表单",
|
||
Code = "PUB_AGAIN",
|
||
Version = 1,
|
||
Status = FormStatus.Published,
|
||
SchemaJson = "{}",
|
||
});
|
||
});
|
||
|
||
var handler = new PublishFormDefinitionCommandHandler(db);
|
||
var command = new PublishFormDefinitionCommand(Id: formId);
|
||
|
||
// Act
|
||
var act = () => handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert
|
||
await act.Should().ThrowAsync<BusinessException>()
|
||
.WithMessage("*已发布*");
|
||
}
|
||
|
||
// ====================================================================
|
||
// DisableFormDefinition
|
||
// ====================================================================
|
||
|
||
[Fact]
|
||
public async Task DisableFormDefinition_ChangesStatusToDisabled()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(DisableFormDefinition_ChangesStatusToDisabled),
|
||
seedAction: ctx =>
|
||
{
|
||
ctx.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "待禁用表单",
|
||
Code = "DIS_FORM",
|
||
Version = 1,
|
||
Status = FormStatus.Published,
|
||
SchemaJson = "{}",
|
||
});
|
||
});
|
||
|
||
var handler = new DisableFormDefinitionCommandHandler(db);
|
||
var command = new DisableFormDefinitionCommand(Id: formId);
|
||
|
||
// Act
|
||
await handler.Handle(command, CancellationToken.None);
|
||
|
||
// Assert
|
||
var entity = await db.FormDefinitions.FindAsync(formId);
|
||
entity.Should().NotBeNull();
|
||
entity!.Status.Should().Be(FormStatus.Disabled);
|
||
}
|
||
|
||
// ====================================================================
|
||
// GetFormDefinitionList
|
||
// ====================================================================
|
||
|
||
[Fact]
|
||
public async Task GetFormDefinitionList_ReturnsPagedResults()
|
||
{
|
||
// Arrange
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(GetFormDefinitionList_ReturnsPagedResults),
|
||
seedAction: ctx =>
|
||
{
|
||
for (int i = 1; i <= 15; i++)
|
||
{
|
||
ctx.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
Name = $"表单_{i:D3}",
|
||
Code = $"FORM_{i:D3}",
|
||
Version = 1,
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
});
|
||
}
|
||
});
|
||
|
||
var handler = new GetFormDefinitionListQueryHandler(db);
|
||
var query = new GetFormDefinitionListQuery(PageIndex: 1, PageSize: 10, Status: null);
|
||
|
||
// Act
|
||
var result = await handler.Handle(query, CancellationToken.None);
|
||
|
||
// Assert
|
||
result.Should().NotBeNull();
|
||
result.Items.Should().HaveCount(10);
|
||
result.TotalCount.Should().Be(15);
|
||
result.PageIndex.Should().Be(1);
|
||
result.PageSize.Should().Be(10);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetFormDefinitionList_FiltersByStatus()
|
||
{
|
||
// Arrange
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(GetFormDefinitionList_FiltersByStatus),
|
||
seedAction: ctx =>
|
||
{
|
||
ctx.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
Name = "草稿表单",
|
||
Code = "DRAFT_001",
|
||
Version = 1,
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
});
|
||
ctx.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
Name = "已发布表单A",
|
||
Code = "PUB_001",
|
||
Version = 1,
|
||
Status = FormStatus.Published,
|
||
SchemaJson = "{}",
|
||
});
|
||
ctx.FormDefinitions.Add(new Domain.Entities.FormDefinition
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
Name = "已发布表单B",
|
||
Code = "PUB_002",
|
||
Version = 1,
|
||
Status = FormStatus.Published,
|
||
SchemaJson = "{}",
|
||
});
|
||
});
|
||
|
||
var handler = new GetFormDefinitionListQueryHandler(db);
|
||
var query = new GetFormDefinitionListQuery(PageIndex: 1, PageSize: 10, Status: FormStatus.Published);
|
||
|
||
// Act
|
||
var result = await handler.Handle(query, CancellationToken.None);
|
||
|
||
// Assert
|
||
result.Should().NotBeNull();
|
||
result.Items.Should().HaveCount(2);
|
||
result.Items.Should().OnlyContain(dto => dto.Status == FormStatus.Published);
|
||
}
|
||
|
||
// ====================================================================
|
||
// GetFormDefinitionById
|
||
// ====================================================================
|
||
|
||
[Fact]
|
||
public async Task GetFormDefinitionById_ReturnsDefinitionWithFields()
|
||
{
|
||
// Arrange
|
||
var formId = Guid.NewGuid();
|
||
await using var db = await _fixture.CreateDbContextWithSeedAsync(
|
||
testName: nameof(GetFormDefinitionById_ReturnsDefinitionWithFields),
|
||
seedAction: ctx =>
|
||
{
|
||
var form = new Domain.Entities.FormDefinition
|
||
{
|
||
Id = formId,
|
||
Name = "带字段的表单",
|
||
Code = "WITH_FIELDS",
|
||
Version = 1,
|
||
Description = "包含多个字段的表单",
|
||
Status = FormStatus.Draft,
|
||
SchemaJson = "{}",
|
||
};
|
||
form.Fields.Add(new Domain.Entities.FormDefinitionField
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
FormDefinitionId = formId,
|
||
FieldKey = "title",
|
||
Label = "标题",
|
||
FieldType = FieldType.Input,
|
||
Required = true,
|
||
Config = "{}",
|
||
SortOrder = 0,
|
||
});
|
||
form.Fields.Add(new Domain.Entities.FormDefinitionField
|
||
{
|
||
Id = Guid.NewGuid(),
|
||
FormDefinitionId = formId,
|
||
FieldKey = "content",
|
||
Label = "内容",
|
||
FieldType = FieldType.RichText,
|
||
Required = false,
|
||
Config = "{}",
|
||
SortOrder = 1,
|
||
});
|
||
ctx.FormDefinitions.Add(form);
|
||
});
|
||
|
||
var handler = new GetFormDefinitionByIdQueryHandler(db);
|
||
var query = new GetFormDefinitionByIdQuery(Id: formId);
|
||
|
||
// Act
|
||
var result = await handler.Handle(query, CancellationToken.None);
|
||
|
||
// Assert
|
||
result.Should().NotBeNull();
|
||
result.Id.Should().Be(formId);
|
||
result.Name.Should().Be("带字段的表单");
|
||
result.Code.Should().Be("WITH_FIELDS");
|
||
result.Fields.Should().NotBeNull();
|
||
result.Fields.Should().HaveCount(2);
|
||
result.Fields.Select(f => f.FieldKey).Should().Contain(["title", "content"]);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task GetFormDefinitionById_NotFound_ThrowsNotFoundException()
|
||
{
|
||
// Arrange
|
||
await using var db = _fixture.CreateDbContext(testName: nameof(GetFormDefinitionById_NotFound_ThrowsNotFoundException));
|
||
var handler = new GetFormDefinitionByIdQueryHandler(db);
|
||
var query = new GetFormDefinitionByIdQuery(Id: Guid.NewGuid());
|
||
|
||
// Act
|
||
var act = () => handler.Handle(query, CancellationToken.None);
|
||
|
||
// Assert
|
||
await act.Should().ThrowAsync<NotFoundException>()
|
||
.WithMessage("*表单*不存在*");
|
||
}
|
||
}
|