跳到主要内容
版本: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 作为单例服务为未来扩展提供了良好的基础。开发者可通过继承标准测试基类并利用依赖注入机制,在测试用例中便捷地访问和使用预设测试数据,确保测试的可靠性与可维护性。