测试数据准备与管理
本文档引用的文件
test/CMS.Plugin.MyPluginName.TestBase/MyPluginNameDataSeedContributor.cstest/CMS.Plugin.MyPluginName.TestBase/MyPluginNameTestData.cstest/CMS.Plugin.MyPluginName.TestBase/MyPluginNameTestBaseModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.Domain/MyEntityNames/MyEntityNameDataSeedContributor.cs/lmes-template/src/CMS.Plugin.MyPluginName.Domain/MyEntityNames/MyEntityName.cstest/CMS.Plugin.MyPluginName.Domain.Tests/MyPluginNameDomainTestModule.cstest/CMS.Plugin.MyPluginName.Application.Tests/MyPluginNameApplicationTestModule.cstest/CMS.Plugin.MyPluginName.TestBase/MyPluginNameTestBase.cs
目录
- 引言
- 测试数据初始化机制
- MyPluginNameDataSeedContributor 实现分析
- MyPluginNameTestData 单例服务设计
- 测试模块集成与执行流程
- 在测试用例中使用测试数据
- 数据注入条件与控制
- 总结
引言
本文档全面介绍系统中测试数据的初始化与管理机制。重点说明 MyPluginNameDataSeedContributor 如何实现 IDataSeedContributor 接口,在测试启动时自动注入预设数据;分析 MyPluginNameTestData 作为单例服务(ISingletonDependency)如何组织和提供可复用的测试数据集(如 MyEntityName 的示例实例);并提供在测试用例中通过 ServiceProvider 获取测试数据和调用种子贡献者的具体代码范例,确保测试的可重复性与独立性。
测试数据初始化机制
系统采用基于 ABP 框架的模块化测试初始化机制,通过 IDataSeedContributor 接口实现测试数据的自动注入。当测试应用启动时,框架会自动调用所有注册的种子贡献者(Data Seed Contributor),根据上下文条件决定是否注入预设测试数据。
测试数据的注入由 MyPluginNameTestBaseModule 模块在 OnApplicationInitialization 阶段触发,通过 IDataSeeder 服务协调所有 IDataSeedContributor 的执行。这种机制确保了测试环境在运行前已具备一致的数据状态,从而保障测试的可重复性和隔离性。
Diagram sources
test/CMS.Plugin.MyPluginName.TestBase/MyPluginNameTestBaseModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.Domain/MyEntityNames/MyEntityNameDataSeedContributor.cs
Section sources
test/CMS.Plugin.MyPluginName.TestBase/MyPluginNameTestBaseModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.Domain/MyEntityNames/MyEntityNameDataSeedContributor.cs
MyPluginNameDataSeedContributor 实现分析
MyEntityNameDataSeedContributor 类实现了 IDataSeedContributor 接口,负责在测试环境中注入 MyEntityName 实体的预设数据。该类在依赖注入容器中注册为瞬态服务(ITransientDependency),确保每次调用都获得一个新实例。
其核心方法 SeedAsync 接收 DataSeedContext 参数,通过检查上下文中的属性来判断是否需要执行数据种子操作。具体而言,当上下文包含键为 "SeedTestData" 且值为 "SeedTestData" 的条目时,才会调用 SeedMyEntityNameDataAsync 方法注入测试数据。
SeedMyEntityNameDataAsync 方法首先检查数据库中是否已存在 MyEntityName 记录,若为空则创建 80 条示例数据并批量插入。此过程在独立的事务中执行,确保数据一致性。
Diagram sources
/lmes-template/src/CMS.Plugin.MyPluginName.Domain/MyEntityNames/MyEntityNameDataSeedContributor.cs
Section sources
/lmes-template/src/CMS.Plugin.MyPluginName.Domain/MyEntityNames/MyEntityNameDataSeedContributor.cs
MyPluginNameTestData 单例服务设计
MyPluginNameTestData 类被设计为单例服务(ISingletonDependency),用于集中管理和提供可复用的测试数据集。尽管当前实现为空,但其设计意图是作为测试数据的中央仓库,存储如默认用户、预设配置、示例实体等共享测试资源。
作为单例服务,MyPluginNameTestData 在整个测试生命周期内仅创建一次,所有测试用例均可通过依赖注入获取相同的实例,从而保证测试数据的一致性和高效共享。未来可在此类中添加属性或方法来返回特定的测试数据实例,例如:
public class MyPluginNameTestData : ISingletonDependency
{
public MyEntityName DefaultMyEntityName => new(Guid.NewGuid(), "DEFAULT_CODE", "Default Name", 0, "Default Remark");
}
Section sources
test/CMS.Plugin.MyPluginName.TestBase/MyPluginNameTestData.cs
测试模块集成与执行流程
测试模块通过分层依赖的方式集成数据种子机制。MyPluginNameDomainTestModule 依赖于 MyPluginNameTestEntityFrameworkCoreModule,而 MyPluginNameApplicationTestModule 又依赖于 MyPluginNameDomainTestModule,形成清晰的测试依赖链。
MyPluginNameTestBaseModule 作为基础测试模块,配置了测试所需的通用服务,如授权策略和工作单元事务行为。其 OnApplicationInitialization 方法通过 AsyncHelper.RunSync 同步调用 IDataSeeder.SeedAsync(),触发所有种子贡献者的执行。
Diagram sources
test/CMS.Plugin.MyPluginName.Application.Tests/MyPluginNameApplicationTestModule.cstest/CMS.Plugin.MyPluginName.Domain.Tests/MyPluginNameDomainTestModule.cstest/CMS.Plugin.MyPluginName.TestBase/MyPluginNameTestBaseModule.cs
Section sources
test/CMS.Plugin.MyPluginName.Application.Tests/MyPluginNameApplicationTestModule.cstest/CMS.Plugin.MyPluginName.Domain.Tests/MyPluginNameDomainTestModule.cs
在测试用例中使用测试数据
在实际测试用例中,可通过继承 MyPluginNameTestBase<TStartupModule> 基类来获得完整的测试环境支持。该基类提供了 ServiceProvider 属性,可用于获取任何已注册的服务实例。
要手动获取测试数据或调用种子贡献者,可使用以下模式:
// 获取测试数据服务
var testData = ServiceProvider.GetRequiredService<MyPluginNameTestData>();
// 获取并调用种子贡献者(通常由框架自动调用)
var dataSeedContributor = ServiceProvider.GetRequiredService<MyEntityNameDataSeedContributor>();
await dataSeedContributor.SeedAsync(new DataSeedContext(ServiceProvider)
.WithProperty("SeedTestData", "SeedTestData"));
更常见的做法是直接使用已注入的仓储服务验证数据状态:
var repository = GetRequiredService<IMyEntityNameRepository>();
var count = await repository.GetCountAsync();
Assert.True(count > 0); // 确保测试数据已注入
Section sources
test/CMS.Plugin.MyPluginName.TestBase/MyPluginNameTestBase.cstest/CMS.Plugin.MyPluginName.Domain.Tests/MyPluginNameDomainTestBase.cs
数据注入条件与控制
系统通过 DataSeedContext 的属性机制精确控制测试数据的注入时机。只有当上下文包含特定键值对时才会执行数据注入:
- 键名:
"SeedTestData" - 键值:
"SeedTestData"
这种设计允许在不同测试场景下灵活控制数据注入行为。例如,在性能测试中可以跳过大量测试数据的注入,而在功能测试中则确保数据环境完整。同时,通过检查数据库中是否已存在数据(GetCountAsync() == 0)来避免重复插入,保证测试的幂等性。
总结
测试数据通过 IDataSeedContributor 和 MyPluginNameTestBaseModule 注入。MyPluginNameTestData 作为单例服务,测试用例可通过标准测试基类和依赖注入获取预设数据。