跳到主要内容
版本:Next

测试数据准备与管理

本文档引用的文件

目录​

  1. 引言
  2. 测试数据初始化机制
  3. MyPluginNameDataSeedContributor 实现分析
  4. MyPluginNameTestData 单例服务设计
  5. 测试模块集成与执行流程
  6. 在测试用例中使用测试数据
  7. 数据注入条件与控制
  8. 总结

引言​

本文档全面介绍系统中测试数据的初始化与管理机制。重点说明 MyPluginNameDataSeedContributor 如何实现 IDataSeedContributor 接口,在测试启动时自动注入预设数据;分析 MyPluginNameTestData 作为单例服务(ISingletonDependency)如何组织和提供可复用的测试数据集(如 MyEntityName 的示例实例);并提供在测试用例中通过 ServiceProvider 获取测试数据和调用种子贡献者的具体代码范例,确保测试的可重复性与独立性。

测试数据初始化机制​

系统采用基于 ABP 框架的模块化测试初始化机制,通过 IDataSeedContributor 接口实现测试数据的自动注入。当测试应用启动时,框架会自动调用所有注册的种子贡献者(Data Seed Contributor),根据上下文条件决定是否注入预设测试数据。

测试数据的注入由 MyPluginNameTestBaseModule 模块在 OnApplicationInitialization 阶段触发,通过 IDataSeeder 服务协调所有 IDataSeedContributor 的执行。这种机制确保了测试环境在运行前已具备一致的数据状态,从而保障测试的可重复性和隔离性。

Diagram sources

Section sources

MyPluginNameDataSeedContributor 实现分析​

MyEntityNameDataSeedContributor 类实现了 IDataSeedContributor 接口,负责在测试环境中注入 MyEntityName 实体的预设数据。该类在依赖注入容器中注册为瞬态服务(ITransientDependency),确保每次调用都获得一个新实例。

其核心方法 SeedAsync 接收 DataSeedContext 参数,通过检查上下文中的属性来判断是否需要执行数据种子操作。具体而言,当上下文包含键为 "SeedTestData" 且值为 "SeedTestData" 的条目时,才会调用 SeedMyEntityNameDataAsync 方法注入测试数据。

SeedMyEntityNameDataAsync 方法首先检查数据库中是否已存在 MyEntityName 记录,若为空则创建 80 条示例数据并批量插入。此过程在独立的事务中执行,确保数据一致性。

Diagram sources

Section sources

MyPluginNameTestData 单例服务设计​

MyPluginNameTestData 类被设计为单例服务(ISingletonDependency),用于集中管理和提供可复用的测试数据集。尽管当前实现为空,但其设计意图是作为测试数据的中央仓库,存储如默认用户、预设配置、示例实体等共享测试资源。

作为单例服务,MyPluginNameTestData 在整个测试生命周期内仅创建一次,所有测试用例均可通过依赖注入获取相同的实例,从而保证测试数据的一致性和高效共享。未来可在此类中添加属性或方法来返回特定的测试数据实例,例如:

public class MyPluginNameTestData : ISingletonDependency
{
public MyEntityName DefaultMyEntityName => new(Guid.NewGuid(), "DEFAULT_CODE", "Default Name", 0, "Default Remark");
}

Section sources

测试模块集成与执行流程​

测试模块通过分层依赖的方式集成数据种子机制。MyPluginNameDomainTestModule 依赖于 MyPluginNameTestEntityFrameworkCoreModule,而 MyPluginNameApplicationTestModule 又依赖于 MyPluginNameDomainTestModule,形成清晰的测试依赖链。

MyPluginNameTestBaseModule 作为基础测试模块,配置了测试所需的通用服务,如授权策略和工作单元事务行为。其 OnApplicationInitialization 方法通过 AsyncHelper.RunSync 同步调用 IDataSeeder.SeedAsync(),触发所有种子贡献者的执行。

Diagram sources

Section sources

在测试用例中使用测试数据​

在实际测试用例中,可通过继承 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

数据注入条件与控制​

系统通过 DataSeedContext 的属性机制精确控制测试数据的注入时机。只有当上下文包含特定键值对时才会执行数据注入:

  • 键名: "SeedTestData"
  • 键值: "SeedTestData"

这种设计允许在不同测试场景下灵活控制数据注入行为。例如,在性能测试中可以跳过大量测试数据的注入,而在功能测试中则确保数据环境完整。同时,通过检查数据库中是否已存在数据(GetCountAsync() == 0)来避免重复插入,保证测试的幂等性。

总结​

本文档详细分析了系统的测试数据准备与管理机制。通过 IDataSeedContributor 接口和 MyPluginNameTestBaseModule 的协同工作,实现了测试数据的自动化、条件化注入。MyPluginNameTestData 作为单例服务为未来扩展提供了良好的基础。开发者可通过继承标准测试基类并利用依赖注入机制,在测试用例中便捷地访问和使用预设测试数据,确保测试的可靠性与可维护性。