单元测试与集成测试
本文档引用的文件
- MyPluginNameTestBase.cs
- MyPluginNameTestData.cs
- MyPluginNameDataSeedContributor.cs
- MyPluginNameTestBaseModule.cs
- MyPluginNameApplicationTestBase.cs
- MyPluginNameDomainTestBase.cs
- MyPluginNameEntityFrameworkTestBase.cs
- MyPluginNameApplicationTestModule.cs
- MyPluginNameDomainTestModule.cs
- MyPluginNameTestEntityFrameworkCoreModule.cs
- CMS.Plugin.MyPluginName.TestBase.csproj
- CMS.Plugin.MyPluginName.Application.Tests.csproj
- CMS.Plugin.MyPluginName.Domain.Tests.csproj
- CMS.Plugin.MyPluginName.EntityFrameworkCore.Tests.csproj
目录
测试体系概述
本项目构建了完整的测试体系,采用分层测试策略,涵盖领域层、应用层和实体框架层的单元测试与集成测试。测试体系基于ABP框架的测试基础设施,通过分层依赖和模块化设计,确保各层测试能够独立运行同时又能进行完整的集成验证。测试体系支持并行执行、事务回滚和内存数据库等特性,保证测试的独立性和可重复性。
测 试项目结构划分
项目中的测试体系按照功能和测试范围划分为四个主要部分:
- CMS.Plugin.MyPluginName.TestBase: 测试基础库,提供所有测试共享的基类、测试数据和公共设施
- CMS.Plugin.MyPluginName.Domain.Tests: 领域层测试,专注于业务逻辑、实体行为和领域服务的测试
- CMS.Plugin.MyPluginName.Application.Tests: 应用层测试,验证应用服务、DTO转换和API契约的正确性
- CMS.Plugin.MyPluginName.EntityFrameworkCore.Tests: 实体框架核心测试,确保数据访问层和数据库交互的正确性
这种分层结构遵循了领域驱动设计的原则,确保测试能够准确覆盖各层的职责边界。
Section sources
- MyPluginNameTestBase.cs
- MyPluginNameApplicationTestBase.cs
- MyPluginNameDomainTestBase.cs
- MyPluginNameEntityFrameworkTestBase.cs
测试基类与公共设施
MyPluginNameTestBase<TStartupModule> 是所有测试类的基类,继承自ABP框架的 AbpIntegratedTest<TStartupModule>,为测试提供了完整的依赖注入容器和应用上下文。
Diagram sources
该基类提供了以下关键功能:
- 依赖注入容器配置: 通过重写
SetAbpApplicationCreationOptions方法配置使用Autofac作为DI容器 - 工作单元支持: 提供了多个
WithUnitOfWorkAsync重载方法,便于在测试中管理事务边界 - 服务获取: 继承自
AbpIntegratedTest,可以直接通过GetRequiredService<T>()获取任何已注册的服务
Section sources
测试数据管理
测试数据通过 MyPluginNameTestData 类进行组织和管理,该类实现了 ISingletonDependency 接口,确保在整个测试生命周期内作为单例存在。
Diagram sources
MyPluginNameDataSeedContributor 作为数据种子贡献者,负责在测试初始化时准备测试数据。它通过依赖注入获取 MyPluginNameTestData 实例和 IGuidGenerator,可以在 SeedAsync 方法中创建预设的测试数据。
Section sources
测试模块依赖关系
测试体系通过ABP模块化架构建立了清晰的依赖关系链,确保各层测试能够正确初始化所需的依赖。
Diagram sources
- MyPluginNameApplicationTestModule.cs
- MyPluginNameDomainTestModule.cs
- MyPluginNameTestEntityFrameworkCoreModule.cs
- MyPluginNameTestBaseModule.cs
各测试模块的职责如下:
- MyPluginNameTestBaseModule: 基础测试模块,配置测试环境通用设置,如授权和工作单元默认选项
- MyPluginNameTestEntityFrameworkCoreModule: 实体框架测试模块,配置使用SQLite内存数据库
- MyPluginNameDomainTestModule: 领域测试模块,依赖实体框架测试模块
- MyPluginNameApplicationTestModule: 应用测试模块,依赖领域测试模块和应用模块
Section sources
- MyPluginNameApplicationTestModule.cs
- MyPluginNameDomainTestModule.cs
- MyPluginNameTestEntityFrameworkCoreModule.cs
- MyPluginNameTestBaseModule.cs
数据库测试配置
为了确保测试的独立性和性能,实体框架测试模块配置了SQLite内存数据库作为测试数据库。
Diagram sources
MyPluginNameTestEntityFrameworkCoreModule 在 ConfigureServices 方法中创建了一个SQLite内存数据库连接,并配置了 AbpDbContextOptions 使用该连接。通过 CreateDatabaseAndGetConnection 方法,确保每次测试运行时都有一个干净的数据库状态。
Section sources
事务与数据隔离
测试体系通过工作单元模式和事务管理确保测试的数据隔离性。MyPluginNameTestBase 提供了 WithUnitOfWorkAsync 系列方法,允许测试在事务上下文中执行操作。
Diagram sources
在 MyPluginNameTestBaseModule 中,通过配置 AbpUnitOfWorkDefaultOptions 将事务行为设置为启用状态,确保所有数据库操作都在事务保护下进行。测试结束后,事务会自动回滚,保证测试间的数据隔离。
Section sources
最佳实践建议
基于本项目的测试体系,以下是编写高质量测试用例的最佳实践:
-
选择合适的测试基类:
- 领域层测试应继承
MyPluginNameDomainTestBase - 应用层测试应继承
MyPluginNameApplicationTestBase - 实体框架测试应继承
MyPluginNameEntityFrameworkTestBase
- 领域层测试应继承
-
使用工作单元模式: 对于涉及数据库操作的测试,使用
WithUnitOfWorkAsync方法确保操作在事务上下文中执行。 -
测试数据准备: 通过扩展
MyPluginNameTestData类来组织预设测试数据,并在MyPluginNameDataSeedContributor的SeedAsync方法中初始化这些数据。 -
并行测试注意事项: 由于使用了内存数据库和事务回滚,测试可以安全地并行执行。确保测试不依赖外部状态或静态变量。
-
断言策略: 使用Shouldly等断言库编写清晰、可读的断言语句,确保测试失败时能提供有意义的错误信息。
-
Mock使用: 对于外部服务依赖,使用NSubstitute等Mock框架创建测试替身,确保测试的独立性。
-
测试命名规范: 采用
MethodName_StateUnderTest_ExpectedBehavior的命名约定,提高测试的可读性和可维护性。 -
测试覆盖率: 确保关键业务逻辑、边界条件和异常路径都有相应的测试覆盖。
Section sources