Skip to main content
Version: Next

Test Data Preparation and Management

Files referenced in this document

Table of Contents​

  1. Introduction
  2. Test Data Initialization Mechanism
  3. MyPluginNameDataSeedContributor Implementation Analysis
  4. MyPluginNameTestData Singleton Service Design
  5. Test Module Integration and Execution Flow
  6. Using Test Data in Test Cases
  7. Data Injection Conditions and Control
  8. Conclusion

Introduction​

This document comprehensively introduces the test data initialization and management mechanism in the system. It focuses on how MyPluginNameDataSeedContributor implements the IDataSeedContributor interface to automatically inject preset data at test startup; analyzes how MyPluginNameTestData as a singleton service (ISingletonDependency) organizes and provides reusable test datasets (such as MyEntityName example instances); and provides code examples for acquiring test data via ServiceProvider and calling seed contributors in test cases, ensuring test repeatability and independence.

Test Data Initialization Mechanism​

The system adopts a modular test initialization mechanism based on the ABP framework, implementing automatic test data injection via the IDataSeedContributor interface. When the test application starts, the framework automatically calls all registered data seed contributors and decides whether to inject preset test data based on context conditions.

Test data injection is triggered by the MyPluginNameTestBaseModule module during the OnApplicationInitialization phase, coordinating the execution of all IDataSeedContributors via the IDataSeeder service. This mechanism ensures the test environment has a consistent data state before running, thus guaranteeing test repeatability and isolation.

Diagram sources

Section sources

MyPluginNameDataSeedContributor Implementation Analysis​

The MyEntityNameDataSeedContributor class implements the IDataSeedContributor interface and is responsible for injecting preset data for the MyEntityName entity in the test environment. This class is registered as a transient service (ITransientDependency) in the dependency injection container, ensuring a new instance is obtained for each call.

Its core method SeedAsync accepts a DataSeedContext parameter and determines whether to execute data seeding by checking properties in the context. Specifically, SeedMyEntityNameDataAsync is called to inject test data only when the context contains an entry with key "SeedTestData" and value "SeedTestData".

The SeedMyEntityNameDataAsync method first checks if MyEntityName records already exist in the database. If empty, it creates 80 sample data records and inserts them in a batch. This process is executed in an independent transaction to ensure data consistency.

Diagram sources

Section sources

MyPluginNameTestData Singleton Service Design​

The MyPluginNameTestData class is designed as a singleton service (ISingletonDependency) to centrally manage and provide reusable test datasets. Although currently empty, its design intent is to act as a central repository for test data, storing shared test resources such as default users, preset configurations, and sample entities.

As a singleton service, MyPluginNameTestData is created only once throughout the entire test lifecycle. All test cases can obtain the same instance via dependency injection, ensuring consistency and efficient sharing of test data. Future extensions can add properties or methods to this class to return specific test data instances, for example:

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

Section sources

Test Module Integration and Execution Flow​

Test modules integrate the data seeding mechanism via layered dependencies. MyPluginNameDomainTestModule depends on MyPluginNameTestEntityFrameworkCoreModule, and MyPluginNameApplicationTestModule depends on MyPluginNameDomainTestModule, forming a clear test dependency chain.

MyPluginNameTestBaseModule, as the base test module, configures general services required for testing, such as authorization policies and unit of work transaction behavior. Its OnApplicationInitialization method synchronously calls IDataSeeder.SeedAsync() via AsyncHelper.RunSync, triggering the execution of all seed contributors.

Diagram sources

Section sources

Using Test Data in Test Cases​

In actual test cases, full test environment support can be obtained by inheriting the MyPluginNameTestBase<TStartupModule> base class. This base class provides the ServiceProvider property, which can be used to retrieve any registered service instance.

To manually retrieve test data or call seed contributors, use the following pattern:

// Get test data service
var testData = ServiceProvider.GetRequiredService<MyPluginNameTestData>();

// Get and call seed contributor (usually called automatically by framework)
var dataSeedContributor = ServiceProvider.GetRequiredService<MyEntityNameDataSeedContributor>();
await dataSeedContributor.SeedAsync(new DataSeedContext(ServiceProvider)
.WithProperty("SeedTestData", "SeedTestData"));

A more common practice is to verify data state directly using injected repository services:

var repository = GetRequiredService<IMyEntityNameRepository>();
var count = await repository.GetCountAsync();
Assert.True(count > 0); // Ensure test data is injected

Section sources

Data Injection Conditions and Control​

The system precisely controls the timing of test data injection via properties of DataSeedContext. Data injection is executed only when the context contains a specific key-value pair:

  • Key: "SeedTestData"
  • Value: "SeedTestData"

This design allows flexible control of data injection behavior in different test scenarios. For example, large amounts of test data injection can be skipped in performance tests, while ensuring a complete data environment in functional tests. Meanwhile, checking if data already exists in the database (GetCountAsync() == 0) avoids duplicate insertion, ensuring test idempotency.

Conclusion​

This document detailed the system's test data preparation and management mechanism. Through the collaboration of the IDataSeedContributor interface and MyPluginNameTestBaseModule, automated and conditional test data injection is achieved. MyPluginNameTestData as a singleton service provides a good foundation for future extensions. Developers can easily access and use preset test data in test cases by inheriting standard test base classes and leveraging the dependency injection mechanism, ensuring test reliability and maintainability.