跳到主要内容
版本:Next

单元测试与集成测试

本文档引用的文件

目录

  1. 测试体系概述
  2. 测试项目结构划分
  3. 测试基类与公共设施
  4. 测试数据管理
  5. 测试模块依赖关系
  6. 数据库测试配置
  7. 事务与数据隔离
  8. 最佳实践建议

测试体系概述

本项目构建了完整的测试体系,采用分层测试策略,涵盖领域层、应用层和实体框架层的单元测试与集成测试。测试体系基于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<TStartupModule> 是所有测试类的基类,继承自ABP框架的 AbpIntegratedTest<TStartupModule>,为测试提供了完整的依赖注入容器和应用上下文。

Diagram sources

该基类提供了以下关键功能:

  1. 依赖注入容器配置: 通过重写 SetAbpApplicationCreationOptions 方法配置使用Autofac作为DI容器
  2. 工作单元支持: 提供了多个 WithUnitOfWorkAsync 重载方法,便于在测试中管理事务边界
  3. 服务获取: 继承自 AbpIntegratedTest,可以直接通过 GetRequiredService<T>() 获取任何已注册的服务

Section sources

测试数据管理

测试数据通过 MyPluginNameTestData 类进行组织和管理,该类实现了 ISingletonDependency 接口,确保在整个测试生命周期内作为单例存在。

Diagram sources

MyPluginNameDataSeedContributor 作为数据种子贡献者,负责在测试初始化时准备测试数据。它通过依赖注入获取 MyPluginNameTestData 实例和 IGuidGenerator,可以在 SeedAsync 方法中创建预设的测试数据。

Section sources

测试模块依赖关系

测试体系通过ABP模块化架构建立了清晰的依赖关系链,确保各层测试能够正确初始化所需的依赖。

Diagram sources

各测试模块的职责如下:

  • MyPluginNameTestBaseModule: 基础测试模块,配置测试环境通用设置,如授权和工作单元默认选项
  • MyPluginNameTestEntityFrameworkCoreModule: 实体框架测试模块,配置使用SQLite内存数据库
  • MyPluginNameDomainTestModule: 领域测试模块,依赖实体框架测试模块
  • MyPluginNameApplicationTestModule: 应用测试模块,依赖领域测试模块和应用模块

Section sources

数据库测试配置

为了确保测试的独立性和性能,实体框架测试模块配置了SQLite内存数据库作为测试数据库。

Diagram sources

MyPluginNameTestEntityFrameworkCoreModuleConfigureServices 方法中创建了一个SQLite内存数据库连接,并配置了 AbpDbContextOptions 使用该连接。通过 CreateDatabaseAndGetConnection 方法,确保每次测试运行时都有一个干净的数据库状态。

Section sources

事务与数据隔离

测试体系通过工作单元模式和事务管理确保测试的数据隔离性。MyPluginNameTestBase 提供了 WithUnitOfWorkAsync 系列方法,允许测试在事务上下文中执行操作。

Diagram sources

MyPluginNameTestBaseModule 中,通过配置 AbpUnitOfWorkDefaultOptions 将事务行为设置为启用状态,确保所有数据库操作都在事务保护下进行。测试结束后,事务会自动回滚,保证测试间的数据隔离。

Section sources

最佳实践建议

基于本项目的测试体系,以下是编写高质量测试用例的最佳实践:

  1. 选择合适的测试基类:

    • 领域层测试应继承 MyPluginNameDomainTestBase
    • 应用层测试应继承 MyPluginNameApplicationTestBase
    • 实体框架测试应继承 MyPluginNameEntityFrameworkTestBase
  2. 使用工作单元模式: 对于涉及数据库操作的测试,使用 WithUnitOfWorkAsync 方法确保操作在事务上下文中执行。

  3. 测试数据准备: 通过扩展 MyPluginNameTestData 类来组织预设测试数据,并在 MyPluginNameDataSeedContributorSeedAsync 方法中初始化这些数据。

  4. 并行测试注意事项: 由于使用了内存数据库和事务回滚,测试可以安全地并行执行。确保测试不依赖外部状态或静态变量。

  5. 断言策略: 使用Shouldly等断言库编写清晰、可读的断言语句,确保测试失败时能提供有意义的错误信息。

  6. Mock使用: 对于外部服务依赖,使用NSubstitute等Mock框架创建测试替身,确保测试的独立性。

  7. 测试命名规范: 采用 MethodName_StateUnderTest_ExpectedBehavior 的命名约定,提高测试的可读性和可维护性。

  8. 测试覆盖率: 确保关键业务逻辑、边界条件和异常路径都有相应的测试覆盖。

Section sources