You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET使用MSTest时无法停止Testcontainers容器的问题

Testcontainers + MSTest + SQL Server集成测试问题解决

一、测试挂起的核心原因及修复

测试挂起、后续代码不执行,主要是两个问题:

  1. 环境变量配置错误:SQL Server容器的官方环境变量不是你写的User Id、Database,必须设置ACCEPT_EULA=Y(同意许可)和SA_PASSWORD(SA账户密码),否则容器内的SQL Server无法正常启动,测试会一直等待。
  2. 误用通用容器:TestcontainersContainer是通用容器,没有内置SQL Server的就绪检测逻辑,StartAsync只会启动容器进程,但不会等待数据库真正可用,导致后续测试代码无法执行。应该用专门的MsSqlContainer,它会自动检测数据库是否就绪。

二、正确的容器配置与测试流程

  1. 先安装必要的NuGet包:Testcontainers.MsSql(专用SQL Server容器包)和MSTest.TestFramework。
  2. 把容器改为实例字段(不要用静态字段),避免类加载时提前初始化导致生命周期不匹配。
  3. 用MsSqlBuilder构建容器,它会自动处理正确的环境变量和就绪检测。

三、数据库初始化与SQL脚本执行

初始化数据库有两种简单方式:

  • 直接执行SQL脚本:用MsSqlContainer的ExecuteScriptAsync方法,直接传入SQL语句或脚本内容。
  • ADO.NET连接操作:通过容器提供的连接字符串,用SqlConnection连接数据库,执行初始化或查询。

四、完整修复后的代码

[TestClass]
public class WithFixtureData
{
    private MsSqlContainer _dbContainer;

    [TestInitialize]
    public async Task StartContainer()
    {
        // 构建专用SQL Server容器,自动处理环境变量和就绪检测
        _dbContainer = new MsSqlBuilder()
            .WithImage("mcr.microsoft.com/mssql/server:2022-latest")
            .WithPassword("YourSTRONG!Passw0rd")
            .WithCleanUp(true) // 测试结束自动清理容器
            .Build();

        // 启动容器,等待数据库就绪后才继续执行
        await _dbContainer.StartAsync();
    }

    [TestMethod]
    public async Task ShouldBringCorrectFixturesBack()
    {
        // 1. 执行SQL脚本初始化表和数据
        await _dbContainer.ExecuteScriptAsync(@"
            CREATE TABLE TestTable (Id INT PRIMARY KEY, Name NVARCHAR(50));
            INSERT INTO TestTable VALUES (1, 'SampleData');
        ");

        // 2. 连接数据库查询并断言
        await using var connection = new SqlConnection(_dbContainer.GetConnectionString());
        await connection.OpenAsync();

        await using var command = new SqlCommand("SELECT Name FROM TestTable WHERE Id = 1", connection);
        var retrievedName = await command.ExecuteScalarAsync() as string;

        Assert.AreEqual("SampleData", retrievedName);
    }

    [TestCleanup]
    public async Task DisposeContainer()
    {
        if (_dbContainer != null)
        {
            await _dbContainer.StopAsync();
            await _dbContainer.DisposeAsync();
        }
    }
}

关键细节说明

  • 不用手动配置ACCEPT_EULA:MsSqlBuilder会自动添加这个环境变量,无需手动设置。
  • GetConnectionString()方法:直接生成可用的连接字符串,包含正确的服务器地址(容器映射的端口)、用户名和密码,不用自己拼接。
  • 实例字段替代静态字段:静态容器会在类加载时创建,可能在多个测试方法间共享,导致测试污染;用实例字段可以保证每个测试方法都有独立的容器实例。

内容的提问来源于stack exchange,提问作者clattenburg cake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 12:25:19