Skip to main content
Version: Next

Test Project Structure

Files referenced in this document

Table of Contents​

  1. Introduction
  2. Test Project Structure Overview
  3. Responsibilities and Test Scope of Test Sub-projects
  4. Layered Test Isolation and Dependency Configuration
  5. Integration Test and Unit Test Organization Strategy
  6. Building Test Environments with ABP Module Dependencies
  7. Cross-Project Collaboration Examples
  8. Conclusion

Introduction​

This document details the overall structure of test projects in a plugin-based project based on the ABP framework. It focuses on analyzing the responsibility division, dependency relationships, test scope, and collaboration mechanisms of the four test sub-projects: Application.Tests, Domain.Tests, EntityFrameworkCore.Tests, and TestBase. By analyzing project references in .csproj files and [DependsOn] module dependencies, it reveals the design principles and implementation of the layered testing architecture.

Test Project Structure Overview​

The test project adopts a layered architecture design, containing four core sub-projects:

  • CMS.Plugin.MyPluginName.Application.Tests: Application layer test project
  • CMS.Plugin.MyPluginName.Domain.Tests: Domain layer test project
  • CMS.Plugin.MyPluginName.EntityFrameworkCore.Tests: Data access layer test project
  • CMS.Plugin.MyPluginName.TestBase: Test infrastructure library project

This layered structure achieves separation of concerns for test code, ensuring that tests for each layer can run independently while supporting integration test scenarios through clear dependency relationships.

Diagram sources

Section sources

Responsibilities and Test Scope of Test Sub-projects​

Application.Tests​

The Application.Tests project is responsible for testing the functions of the Application Layer, including application service classes, DTO conversions, permission validation, etc. Its test scope covers the correctness of business logic in application services, input validation, exception handling, etc.

Section sources

Domain.Tests​

The Domain.Tests project focuses on testing the Domain Layer, including entities, value objects, domain services, repository interfaces, etc. Its test scope is mainly core domain logic such as business rules of domain models, invariant constraints, domain events, etc.

Section sources

EntityFrameworkCore.Tests​

The EntityFrameworkCore.Tests project is responsible for integration testing of the data access layer, verifying EF Core related functions such as entity mapping, database queries, transaction processing, etc. It uses SQLite in-memory database for testing to ensure the correctness of database operations.

Section sources

TestBase​

The TestBase project is the test infrastructure library, providing common test base classes, service configurations, data seeds, and other functions for other test projects. It encapsulates the infrastructure for ABP integration testing, including dependency injection, unit of work, in-memory database initialization, etc.

Section sources

Layered Test Isolation and Dependency Configuration​

The dependency relationships of test projects are configured through ProjectReference in .csproj files, implementing top-down layered dependencies:

<!-- Application.Tests depends on Domain.Tests -->
<ProjectReference Include="..\CMS.Plugin.MyPluginName.Domain.Tests\CMS.Plugin.MyPluginName.Domain.Tests.csproj" />

<!-- Domain.Tests depends on EntityFrameworkCore.Tests -->
<ProjectReference Include="..\CMS.Plugin.MyPluginName.EntityFrameworkCore.Tests\CMS.Plugin.MyPluginName.EntityFrameworkCore.Tests.csproj" />

<!-- EntityFrameworkCore.Tests depends on TestBase -->
<ProjectReference Include="..\CMS.Plugin.MyPluginName.TestBase\CMS.Plugin.MyPluginName.TestBase.csproj" />

This dependency configuration achieves test isolation:

  • Application layer tests can depend on domain layer test modules to perform cross-layer integration tests.
  • Domain layer tests depend on data access layer tests to ensure consistency between domain logic and data persistence.
  • Data access layer tests depend on the test infrastructure library to obtain unified test infrastructure.

Diagram sources

Section sources

Integration Test and Unit Test Organization Strategy​

Test projects adopt a layered organization strategy, distinguishing between unit tests and integration tests:

  • Unit Tests: Performed within each layer, using Mocking technology to isolate external dependencies.
  • Integration Tests: Achieved through layered dependencies for cross-layer integration, such as application layer tests integrating domain layer and data access layer.

The test base class design reflects this strategy:

  • MyPluginNameTestBase<TStartupModule> provides ABP integration test foundation.
  • Test base classes for each layer inherit from MyPluginNameTestBase and specify corresponding startup modules.
  • Supports transactional testing via WithUnitOfWorkAsync method.

Diagram sources

Section sources

Building Test Environments with ABP Module Dependencies​

The ABP framework's modular system builds test environments through the [DependsOn] attribute, forming a module dependency chain:

// TestBase Module Dependencies
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpTestBaseModule),
typeof(CMSPluginDomainModule))]
public class MyPluginNameTestBaseModule : AbpModule

// EF Core Test Module Dependencies
[DependsOn(
typeof(MyPluginNameTestBaseModule),
typeof(CMSPluginEntityFrameworkCoreModule),
typeof(AbpEntityFrameworkCoreSqliteModule))]
public class MyPluginNameTestEntityFrameworkCoreModule : AbpModule

// Domain Test Module Dependencies
[DependsOn(typeof(MyPluginNameTestEntityFrameworkCoreModule))]
public class MyPluginNameDomainTestModule : AbpModule

// Application Test Module Dependencies
[DependsOn(
typeof(CMSPluginApplicationModule),
typeof(MyPluginNameDomainTestModule))]
public class MyPluginNameApplicationTestModule : AbpModule

This dependency chain ensures correct initialization of the test environment:

  1. Starts from TestBaseModule, configuring basic services (DI, Unit of Work).
  2. TestEntityFrameworkCoreModule configures EF Core and SQLite in-memory database.
  3. DomainTestModule integrates domain layer functions.
  4. ApplicationTestModule finally integrates application layer services.

Diagram sources

Section sources

Cross-Project Collaboration Examples​

Collaboration between test projects is achieved through layered dependencies and module inheritance. Taking application layer testing as an example, it depends on the domain layer test module, allowing cross-layer integration testing:

// ApplicationTestModule depends on DomainTestModule
[DependsOn(
typeof(CMSPluginApplicationModule),
typeof(MyPluginNameDomainTestModule))] // Directly depends on domain test module
public class MyPluginNameApplicationTestModule : AbpModule

This design allows application service tests to directly use the full implementation of the domain layer, including:

  • Validation of domain entities and business rules
  • Repository implementation and database interaction
  • Domain event publishing and handling

At the same time, by inheriting MyPluginNameTestBase<MyPluginNameApplicationTestModule> via MyPluginNameApplicationTestBase, complete test infrastructure is obtained, including:

  • Dependency injection container
  • Unit of work management
  • In-memory database access
  • Data seeding service

Diagram sources

Section sources

Conclusion​

This test architecture achieves clear separation of concerns and effective test isolation through the layered design of four test sub-projects. TestBase serves as the foundation layer providing common test facilities, EntityFrameworkCore.Tests provides data access testing capabilities, Domain.Tests focuses on domain logic validation, and Application.Tests is responsible for integration testing of application services.

Dependency relationships are doubly guaranteed by project references in .csproj files and the [DependsOn] attribute of ABP modules, achieving both compile-time dependency management and runtime module initialization order. This design supports various test scenarios from unit testing to full-stack integration testing, providing a solid foundation for quality assurance of plugin-based systems.