TestContainers 在 .NET 中需使用社区库 DotNet.Testcontainers(非官方),安装命令为 dotnet add package DotNet.Testcontainers;必须运行 Docker Desktop(Linux 需加入 docker 组),容器启动需显式调用 StartAsync/StopAsync,连接时 Host 应用 host.docker.internal(CI 用 172.17.0.1)。

TestContainers 在 .NET 中不原生支持,得靠 Testcontainers-dotnet
TestContainers 官方库只支持 Java、Go、Node.js 等语言,Testcontainers(注意大小写)在 C# 里不是官方项目,而是社区维护的 Testcontainers-dotnet。直接 NuGet 搜索 Testcontainers 会找到它,但包名是 DotNet.Testcontainers —— 这是第一个容易装错的地方。
正确安装方式:
dotnet add package DotNet.Testcontainers
别装成 Testcontainers(已废弃)或 Testcontainers.Xunit(仅提供 xUnit 集成,不包含核心容器逻辑)。
- 必须引用
DotNet.Testcontainers才能创建和管理容器 -
Testcontainers.Xunit可选,仅当你用 xUnit 且想用[CollectionDefinition]共享容器时才需要 - .NET 6+ 是硬性要求;.NET Framework 不支持
启动 PostgreSQL 容器失败:Docker Desktop 未运行或权限不足
最常见报错是 Unable to connect to Docker daemon 或 Docker API responded with status code=NotFound,本质不是代码问题,而是环境没就绪。
关键检查点:
- Docker Desktop 必须正在运行(Windows/macOS),且“Start Docker Desktop when you log in”已启用
- Linux 用户需确认当前用户在
docker组中:sudo usermod -aG docker $USER,然后重新登录终端 - 若用 WSL2,确保 Docker Desktop 的 “Use the WSL 2 based engine” 已勾选,并在 WSL 内执行
docker info能返回结果 - 避免在 CI(如 GitHub Actions)中漏掉
services声明或docker://runtime
代码里别依赖“自动重试”,先确保 docker ps 能跑通再写测试。
容器生命周期管理不当导致端口冲突或资源泄漏
很多人把 ITestcontainer 当作普通对象 new 出来就完事,结果测试并行跑时抢同一个端口,或测试结束后容器还在后台运行。
正确做法:
- 用
await container.StartAsync()启动,await container.StopAsync()显式停止 —— 不要依赖析构函数或IDisposable的Dispose(它不 await) - 在 xUnit 中,用
IAsyncLifetime接口统一管理启停,而非在每个[Fact]里重复写 - 为容器指定唯一网络别名(
WithNetworkAliases("pg-test"))和固定内部端口(WithPortBinding(5432, true)),避免宿主机端口随机分配引发不稳定 - 测试类之间不要共享单个容器实例(除非明确用了集合隔离),否则并发执行会出错
示例片段:
public class DatabaseTests : IAsyncLifetime
{
private readonly Container _postgres;
<p>public DatabaseTests()
{
_postgres = new ContainerBuilder()
.WithImage("postgres:15")
.WithEnvironment("POSTGRES_PASSWORD=password")
.WithPortBinding(5432, true)
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(5432))
.Build();
}</p><p>public async Task InitializeAsync() => await _postgres.StartAsync();
public async Task DisposeAsync() => await _postgres.StopAsync();
}连接字符串拼接错误:Host 地址不是 localhost
本地开发时,容器内服务对宿主机的访问路径不是 localhost —— 这是高频翻车点。在 Windows/macOS 上,Docker Desktop 提供 host.docker.internal;在 Linux 上得用网关 IP(如 172.17.0.1)。
更稳妥的做法是让容器加入同一网络,并用容器名通信:
- 启动容器时加
WithNetwork("test-network") - 用
WithNetworkAliases("pg")设置别名 - 连接字符串 Host 写
pg,而不是localhost或127.0.0.1 - 如果测试进程在宿主机跑(绝大多数情况),则必须用
host.docker.internal,且需确认 Docker Desktop 设置中已启用该选项
验证方式:测试里加一行 Console.WriteLine(await _postgres.GetConnectionString());,看输出的 Host 是什么。
真正麻烦的是 CI 环境 —— GitHub Actions 的 ubuntu-latest runner 里没有 host.docker.internal,得改用 172.17.0.1 并确保容器网络模式为 bridge。


















