Testcontainers:“Container %some_id% is not running”,他已启动但已退出

问题描述 投票:0回答:1

我已经有了基于

inMemoryDatabase & XUnit
的集成测试,所以我决定通过
testcontainers 3.5
为 docker 镜像重构它。我试图独自解决它,但陷入了死胡同。

问题是开始创建容器的核心,一开始你应该创建配置并下一步实现

IAsyncLifetime
。完成此步骤后,只需打开 docker,然后运行测试,这是基本的操作方法。经过这些步骤后,我遇到了两个错误:

  1. "System.TimeoutException: The operation has timed out."
    。我不知道为什么,但它出现在
    XUnit
    方法
    "CreateClassFixtureAsync(Type fixtureType)"
    中并掉落在这里:

  2. "Docker API responded with status code=Conflict, response={message:Container %some_id% is not running}"
    发生这种情况是因为在启动的同时,Docker 容器中的状态已更改为
    Exited

我的

Factory.cs
创建容器的类:

public class IntegrationTestApplicationFactory : WebApplicationFactory<Program>, IAsyncLifetime
{

    private const string ImageName = "ubuntu:16.04"; // tips #1
    private const string Database = "master";
    private const string Username = "sa";
    private const string Password = "myStr0ng!&Passw0rd!";
    private int MsSqlPort = Random.Shared.Next(10000, 60000);
    
    private readonly IContainer _mssqlContainer;
    
    public IntegrationTestMalumApplicationFactory()
    {
        _mssqlContainer = new ContainerBuilder()
            .WithImage(ImageName)
            .WithName(Guid.NewGuid().ToString())
            .WithEnvironment("ACCEPT_EULA", "Y")
            .WithEnvironment("SQLCMDUSER", Username)
            .WithEnvironment("SQLCMDPASSWORD", Password)
            .WithEnvironment("MSSQL_SA_PASSWORD", Password)
            .WithEnvironment("MSSQL_PID", "Evaluation")
            .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(MsSqlPort))
            .WithPortBinding(MsSqlPort, true)
            .WithExposedPort(MsSqlPort)
            .WithCleanUp(true)
            .Build();
    }

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        var host = _mssqlContainer.Hostname;
        var port = _mssqlContainer.GetMappedPublicPort(MsSqlPort);
        
        builder.ConfigureTestServices(services =>
        {
            services.RemoveAll(typeof(DbContextOptions<DataAccess.Context>));

            services.AddDbContextPool<DataAccess.Context>((options, optionsBuilder) =>
            {
                optionsBuilder.UseSqlServer(
                    $"Server={host},{port};Database={Database};User Id={Username};Password={Password};TrustServerCertificate=true");
            });
        });
    }

    public async Task InitializeAsync() => await _mssqlContainer.StartAsync();
    public async new Task DisposeAsync() => await _mssqlContainer.StopAsync();
}

我的

Test.cs
看起来像:

public class IntegrationTestMalumApi : IClassFixture<IntegrationTestApplicationFactory>
{
    protected readonly HttpClient TestClient;
    protected readonly ApplicationUrl ApplicationUrl;

    public IntegrationTestMalumApi(IntegrationTestApplicationFactory applicationFactory)
    {
        TestClient = applicationFactory.CreateClient();
        ApplicationUrl = new ApplicationUrl("http://localhost:1324");
    }

    [Fact]
    public async Task GetCats_WithThreeCats_ReturnHttpCodeOK()
    {
        // to do something
    }
}

一些提示:

  1. 尝试使用

    "mcr.microsoft.com/mssql/server:2022-preview-ubuntu-22.04"
    ,但它实际上仅适用于现有的
    imageName

  2. ApplicationUrl
    是包含任何 API 路径的路由的类;

  3. 问题发生在班级

    "CreateClassFixtureAsync(Type fixtureType)"
    "XunitTestClassRunner.cs"

  4. 有时,每当尝试使用

    "InitializeAsync()"
    时,都会在班级
    "IntegrationTestApplicationFactory "
    中发生这种情况
    

  5. 每当我尝试像
  6. "_mssqlContainer.StartAsync()";

    这样使用基本配置的东西时,它也不起作用。

    
    

问题:

你有什么建议吗?我做错了什么?

.net sql-server docker xunit testcontainers
1个回答
0
投票

@AlwaysLearning回答后,我重新设计了它。

解决方案:

所以,他怎么说主要原因是在港口。默认情况下,

MSSQL

的端口应等于"IContainer container = new ContainerBuilder().WithImage(ImageName).Build()",这是我问题的答案,但不是结束。接下来我收到了基于配置的异常,修复是下一个字符串:

"1433"

接下来看代码:

"ACCEPT_EULA=Y"

更多信息,我重新设计了 
private const string ImageName = "mcr.microsoft.com/mssql/server:2022-preview-ubuntu-22.04"; private const ushort MssqlPort = 1433; private const string Database = "master"; private const string Username = "sa"; private const string Password = "myStr0ng!&Passw0rd!"; private const string ContainerName = "integrationtest"; private readonly IContainer _mssqlContainer; public IntegrationTestApplicationFactory() { _mssqlContainer = new ContainerBuilder() .WithImage(ImageName) .WithName(String.Concat(ContainerName, Guid.NewGuid().ToString())) .WithEnvironment("ACCEPT_EULA", "Y") .WithEnvironment("SQLCMDUSER", Username) .WithEnvironment("SQLCMDPASSWORD", Password) .WithEnvironment("MSSQL_SA_PASSWORD", Password) .WithEnvironment("MSSQL_PID", "Evaluation") .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(MssqlPort)) .WithPortBinding(MssqlPort, true) .WithCleanUp(true) .Build(); }

创建 EF 迁移的方法,来源

这里
InitializeAsync

有用的链接:

    需要在防火墙中打开哪些端口才能访问SQL Server?
  1. 如何找到SQL Server正在使用的端口?
© www.soinside.com 2019 - 2024. All rights reserved.