I have an integration tests project that executes as expected in VS. The integration tests use a MsSql testcontainer (from https://dotnet.testcontainers.org/).
My goal is to run these tests in an Azure DevOps pipeline within a docker image, as I do successfully for other projects which do not use testcontainers. For now I am just trying to run the tests within a docker image in my local machine. Unfortunately I am facing connection issues.
My environment:
- .NET 6
- OS: Windows
- Docker Desktop with linux containers
My code:
Authentication.Api/MyProject.Authentication.Api/Dockerfile:
##########################################################
# build
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["Authentication.Api/MyProject.Authentication.Api/MyProject.Authentication.Api.csproj", "Authentication.Api/MyProject.Authentication.Api/"]
COPY ["Authentication.Api/MyProject.Authentication.Api.IntegrationTests/MyProject.Authentication.Api.IntegrationTests.csproj", "Authentication.Api/MyProject.Authentication.Api.IntegrationTests/"]
RUN dotnet restore "Authentication.Api/MyProject.Authentication.Api/MyProject.Authentication.Api.csproj"
RUN dotnet restore "Authentication.Api/MyProject.Authentication.Api.IntegrationTests/MyProject.Authentication.Api.IntegrationTests.csproj"
COPY . .
WORKDIR "/src/Authentication.Api/MyProject.Authentication.Api"
RUN dotnet build "MyProject.Authentication.Api.csproj" -c Release -o /app/build
WORKDIR "/src/Authentication.Api/MyProject.Authentication.Api.IntegrationTests"
RUN dotnet build -c Release
##########################################################
# run test projects
FROM build AS tests
WORKDIR /src
VOLUME /var/run/docker.sock:/var/run/docker.sock
RUN dotnet test --no-build -c Release --results-directory /testresults --logger "trx;LogFileName=testresults_authentication_api_it.trx" /p:CollectCoverage=true /p:CoverletOutputFormat=json%2cCobertura /p:CoverletOutput=/testresults/coverage/ -p:MergeWith=/testresults/coverage/coverage.json Authentication.Api/MyProject.Authentication.Api.IntegrationTests/MyProject.Authentication.Api.IntegrationTests.csproj
##########################################################
# create image
FROM build AS publish
WORKDIR "/src/Authentication.Api/MyProject.Authentication.Api"
RUN dotnet publish "MyProject.Authentication.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS final
WORKDIR /app
EXPOSE 80
EXPOSE 443
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyProject.Authentication.Api.dll"]
Authentication.Api/MyProject.Authentication.Api.IntegrationTests/Factory/CustomWebApplicationFactory.cs:
public class CustomWebApplicationFactory<TProgram, TDbContext> : WebApplicationFactory<TProgram>, IAsyncLifetime, ICustomWebApplicationFactory
where TProgram : class
where TDbContext : DbContext
{
private readonly MsSqlDatabaseProvider _applicationMsSqlDatabaseProvider;
public CustomWebApplicationFactory()
{
_applicationMsSqlDatabaseProvider = new MsSqlDatabaseProvider();
}
protected override void ConfigureWebHost(IWebHostBuilder builder)
=> builder.ConfigureServices(services =>
{
services.Remove(services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<ApplicationDbContext>)) ?? throw new InvalidOperationException());
services.AddDbContext<ApplicationDbContext>(options => { options.UseSqlServer(_applicationMsSqlDatabaseProvider.Database.ConnectionString); });
ServiceProvider? sp = services.BuildServiceProvider();
using IServiceScope scope = sp.CreateScope();
IServiceProvider scopedServices = scope.ServiceProvider;
ILogger<CustomWebApplicationFactory<TProgram, TDbContext>> logger = scopedServices.GetRequiredService<ILogger<CustomWebApplicationFactory<TProgram, TDbContext>>>();
ApplicationDbContext applicationDbContext = scopedServices.GetRequiredService<ApplicationDbContext>();
applicationDbContext.Database.EnsureCreated();
logger.LogInformation("Ensured that the ApplicationDbContext DB is created.");
});
public async Task InitializeAsync() =>
await _applicationMsSqlDatabaseProvider.Database.StartAsync();
public new async Task DisposeAsync() =>
await _applicationMsSqlDatabaseProvider.Database.DisposeAsync().AsTask();
}
{shared library path}/MsSqlDatabaseProvider.cs:
public class MsSqlDatabaseProvider
{
private const string DbPassword = "my_dummy_password#123";
private const string DbImage = "mcr.microsoft.com/mssql/server:2019-latest";
public readonly TestcontainerDatabase Database;
public MsSqlDatabaseProvider() =>
Database = new TestcontainersBuilder<MsSqlTestcontainer>()
.WithDatabase(new MsSqlTestcontainerConfiguration
{
Password = DbPassword,
})
.WithImage(DbImage)
.WithCleanUp(true)
.Build();
}
On command line I run docker build --progress=plain -f Authentication.Api\MyProject.Authentication.Api\Dockerfile --target tests --tag myproject-tests .
.
And I am getting the following error:
Cannot detect the Docker endpoint. Use either the environment variables or the ~/.testcontainers.properties file to customize your configuration: https://dotnet.testcontainers.org/custom_configuration/ (Parameter 'DockerEndpointAuthConfig')
I tried adding the environment variable in docker, changing dockerfile to
RUN export DOCKER_HOST="tcp://192.168.99.100:2376" && dotnet test --no-build -c Release --results-directory /testresults --logger "trx;LogFileName=testresults_authentication_api_it.trx" /p:CollectCoverage=true /p:CoverletOutputFormat=json%2cCobertura /p:CoverletOutput=/testresults/coverage/ -p:MergeWith=/testresults/coverage/coverage.json Authentication.Api/MyProject.Authentication.Api.IntegrationTests/MyProject.Authentication.Api.IntegrationTests.csproj
and adding .WithDockerEndpoint("tcp://192.168.99.100:2376")
in MsSqlDatabaseProvider, but I ended up with another error:
System.Net.Http.HttpRequestException : Connection failed
System.Net.Sockets.SocketException : Connection refused
I do not know what value(s) I should use for docker host / docker endpoint. Or is the solution something else?
Thank you in advance!
RUN export DOCKER_HOST=tcp://host.docker.internal:2375
see more? – Coydocker run
, but I am not aware of a configuration that works during the build. – Shirl