SuperAPI AI 工具集

testcontainers-integration-tests

测试与质量

查看项目

更新于 10-15 01:55

技能介绍

用途

该技能面向 .NET 集成测试场景,帮助开发者在测试中使用真实基础设施而非模拟对象。适用情形包括:需要真实数据库、缓存或消息队列的集成测试;针对实际数据库测试数据访问层;验证消息队列集成;测试 Redis 缓存行为;避免对基础设施组件使用 Mock;确保测试运行在与生产相似的环境中;测试数据库迁移与架构变更。

主要能力

  • 使用 Docker 容器提供真实数据库(SQL Server、PostgreSQL)、缓存(Redis)和消息队列(RabbitMQ)。
  • 提供数据库模式示例(database-patterns.md):SQL Server、PostgreSQL 与迁移测试。
  • 提供基础设施模式示例(infrastructure-patterns.md):Redis、RabbitMQ、多容器网络、容器复用与 Respawn。
  • 覆盖 TestContainers 4.x 的模块构建器 API(3.0+ 模块构建器),并说明旧版类型(如 TestcontainersBuilder<T>、TestcontainersContainer、TestcontainersNetworkBuilder)已被重命名或移除,无法在现代包中编译。
  • 给出所需 NuGet 包与命名空间引用。
  • 提供常见问题(启动超时、端口占用、容器未清理、CI 与本地不一致)的解决方式。
  • 提供 GitHub Actions 的 CI/CD 集成示例。

核心原则

  • 真实基础设施优先于 Mock:使用容器中的真实数据库/服务,而非模拟。
  • 测试隔离:每个测试获得全新容器或全新数据。
  • 自动清理:TestContainers 负责容器生命周期与清理。
  • 快速启动:在合适时于同一测试类中复用容器。
  • 兼容 CI/CD:在支持 Docker 的 CI 环境中可无缝运行。
  • 端口随机化:容器使用随机端口以避免冲突。

使用方式

推荐使用来自 Testcontainers.<Provider> 包的模块构建器,每个模块构建器会为其数据库或服务预配置正确的镜像、环境变量、端口和等待策略。将镜像传入构建器构造函数(而非通过 .WithImage()),以避免使用已过时的无参构造函数。示例:

var container = new PostgreSqlBuilder("postgres:latest")
    .WithDatabase("testdb")
    .WithUsername("postgres")
    .WithPassword("postgres")
    .Build();

所需 NuGet 包(模块包按提供方各一个):

<ItemGroup>
  <!-- Core TestContainers -->
  <PackageReference Include="Testcontainers" Version="*" />

  <!-- Provider modules -->
  <PackageReference Include="Testcontainers.MsSql" Version="*" />
  <PackageReference Include="Testcontainers.PostgreSql" Version="*" />
  <PackageReference Include="Testcontainers.Redis" Version="*" />
  <PackageReference Include="Testcontainers.RabbitMq" Version="*" />

  <PackageReference Include="xunit" Version="*" />
  <PackageReference Include="xunit.runner.visualstudio" Version="*" />

  <!-- Database drivers -->
  <PackageReference Include="Microsoft.Data.SqlClient" Version="*" />
  <PackageReference Include="Npgsql" Version="*" /> <!-- For PostgreSQL -->

  <!-- Other infrastructure -->
  <PackageReference Include="StackExchange.Redis" Version="*" /> <!-- For Redis -->
  <PackageReference Include="RabbitMQ.Client" Version="*" /> <!-- For RabbitMQ -->
</ItemGroup>

所需 using:

using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Networks;
using Testcontainers.MsSql;
using Testcontainers.PostgreSql;
using Testcontainers.Redis;
using Testcontainers.RabbitMq;

模块构建器与容器类型位于各提供方专属命名空间;基础类型(ContainerBuilder、NetworkBuilder、Wait)位于 DotNet.Testcontainers.Builders,INetwork 位于 DotNet.Testcontainers.Networks。

适用场景

  • 数据访问层针对真实数据库的测试。
  • 消息队列集成验证。
  • Redis 缓存行为测试。
  • 数据库迁移与架构变更测试。
  • 需要生产相似环境的集成测试。
  • 在支持 Docker 的 CI 中运行集成测试。

最佳实践

  • 始终使用 IAsyncLifetime 进行正确的异步初始化与清理。
  • 使用 Wait 策略等待端口可用,确保容器就绪。
  • 使用随机端口,让 TestContainers 自动分配。
  • 测试之间清理数据:使用全新容器或截断表。
  • 尽可能复用容器,比每个测试新建更快。
  • 测试真实查询,验证实际 SQL 行为。
  • 验证约束:外键、唯一约束、索引。
  • 测试事务:验证回滚与提交行为。
  • 使用接近生产的数据量。
  • 在 DisposeAsync 中始终释放容器。

常见问题与解决

  • 容器启动超时:通过 WithWaitStrategy 设置等待策略与超时,例如:
_container = new PostgreSqlBuilder("postgres:latest")
    .WithDatabase("testdb")
    .WithUsername("postgres")
    .WithPassword("postgres")
    .WithWaitStrategy(Wait.ForUnixContainer()
        .UntilInternalTcpPortIsAvailable(5432, w => w.WithTimeout(TimeSpan.FromMinutes(2))))
    .Build();
  • 端口已被占用:始终使用随机端口映射。模块构建器默认处理,核心容器构建器可显式设置:
.WithPortBinding(5432, true) // true = assign random public port
  • 容器未清理:确保正确释放:
public async Task DisposeAsync()
{
    await _connection?.DisposeAsync();
    await _container?.DisposeAsync();
}
  • 本地通过但 CI 失败:确保 CI 支持 Docker,例如 GitHub Actions 使用 runs-on: ubuntu-latest(预装 Docker)。

CI/CD 集成示例(GitHub Actions)

name: Integration Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Setup .NET
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: 9.0.x

    - name: Run Integration Tests
      run: |
        dotnet test tests/YourApp.IntegrationTests \
          --filter Category=Integration \
          --logger trx

    - name: Cleanup Containers
      if: always()
      run: docker container prune -f

性能提示

  • 复用容器:在集合中跨测试共享 fixture。
  • 使用 Respawn:无需重建容器即可重置数据。
  • 并行执行:TestContainers 自动处理端口冲突。
  • 使用轻量镜像:Alpine 版本更小更快。
  • 缓存镜像:Docker 会在本地缓存已拉取的镜像。

限制

资料未提供该技能的收费、价格、平台支持范围、效果指标或具体使用步骤之外的额外限制信息。