Test Project Structure
Files referenced in this document
- CMS.Plugin.MyPluginName.Application.Tests.csproj
- CMS.Plugin.MyPluginName.Domain.Tests.csproj
- CMS.Plugin.MyPluginName.EntityFrameworkCore.Tests.csproj
- CMS.Plugin.MyPluginName.TestBase.csproj
- MyPluginNameApplicationTestModule.cs
- MyPluginNameDomainTestModule.cs
- MyPluginNameTestEntityFrameworkCoreModule.cs
- MyPluginNameTestBaseModule.cs
- MyPluginNameApplicationTestBase.cs
- MyPluginNameDomainTestBase.cs
- MyPluginNameEntityFrameworkTestBase.cs
- MyPluginNameTestBase.cs
- CMSPluginApplicationModule.cs
- CMSPluginDomainModule.cs
- CMSPluginEntityFrameworkCoreModule.cs
Table of Contents
- Introduction
- Test Project Structure Overview
- Responsibilities and Test Scope of Test Sub-projects
- Layered Test Isolation and Dependency Configuration
- Integration Test and Unit Test Organization Strategy
- Building Test Environments with ABP Module Dependencies
- Cross-Project Collaboration Examples
- 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 projectCMS.Plugin.MyPluginName.Domain.Tests: Domain layer test projectCMS.Plugin.MyPluginName.EntityFrameworkCore.Tests: Data access layer test projectCMS.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
- CMS.Plugin.MyPluginName.Application.Tests.csproj
- CMS.Plugin.MyPluginName.Domain.Tests.csproj
- CMS.Plugin.MyPluginName.EntityFrameworkCore.Tests.csproj
- CMS.Plugin.MyPluginName.TestBase.csproj
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
- CMS.Plugin.MyPluginName.Application.Tests.csproj
- CMS.Plugin.MyPluginName.Domain.Tests.csproj
- CMS.Plugin.MyPluginName.EntityFrameworkCore.Tests.csproj
- CMS.Plugin.MyPluginName.TestBase.csproj
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
MyPluginNameTestBaseand specify corresponding startup modules. - Supports transactional testing via
WithUnitOfWorkAsyncmethod.
Diagram sources
- MyPluginNameTestBase.cs
- MyPluginNameApplicationTestBase.cs
- MyPluginNameDomainTestBase.cs
- MyPluginNameEntityFrameworkTestBase.cs
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:
- Starts from
TestBaseModule, configuring basic services (DI, Unit of Work). TestEntityFrameworkCoreModuleconfigures EF Core and SQLite in-memory database.DomainTestModuleintegrates domain layer functions.ApplicationTestModulefinally integrates application layer services.
Diagram sources
- MyPluginNameTestBaseModule.cs
- MyPluginNameTestEntityFrameworkCoreModule.cs
- MyPluginNameDomainTestModule.cs
- MyPluginNameApplicationTestModule.cs
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.