C
C#12mo ago
michalgrzyska

Testcontainers in integration tests vs BackgroundService

I have an issue with Testcontainers + WebApplicationFactory in integration test. I created my implementation of WebApplicationFactory implementing IAsyncLifetime from xUnit and I'm migrating my EF Core context in InitializeAsync method. However, it is probably too late - one of my background services tries to access in StartAsync (with ServiceProvider scope) db context to check some data and it results with an exception of "column ... does not exist". Is there any workaround for managing that problem? code in comment
1 Reply
michalgrzyska
michalgrzyskaOP12mo ago
code:
public class TestApplicationFactory : WebApplicationFactory<Program>, IAsyncLifetime
{
private DbConnection _dbConnection = null!;
private Respawner _respawner = null!;

private readonly PostgreSqlContainer _dbContainer = new PostgreSqlBuilder()
.WithDatabase("db")
.WithUsername("user")
.WithPassword("password")
.Build();

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureTestServices(services =>
{
services.RemoveAll<DbContextOptions<MyContext>>();
services.RemoveAll<MyContext>();

services.AddDbContext<MyContext>(x => x.UseNpgsql(_dbContainer.GetConnectionString()));
});
}

public async Task InitializeAsync()
{
await _dbContainer.StartAsync();

_dbConnection = new NpgsqlConnection(_dbContainer.GetConnectionString());
await _dbConnection.OpenAsync();

using var scope = Services.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<MyContext>();
await dbContext.Database.MigrateAsync();

_respawner = await Respawner.CreateAsync(_dbConnection, new RespawnerOptions
{
DbAdapter = DbAdapter.Postgres,
SchemasToInclude = ["public"]
});
}

public async Task ResetDatabaseAsync() => await _respawner.ResetAsync(_dbConnection);
public new async Task DisposeAsync() => await _dbContainer.StopAsync();
}
public class TestApplicationFactory : WebApplicationFactory<Program>, IAsyncLifetime
{
private DbConnection _dbConnection = null!;
private Respawner _respawner = null!;

private readonly PostgreSqlContainer _dbContainer = new PostgreSqlBuilder()
.WithDatabase("db")
.WithUsername("user")
.WithPassword("password")
.Build();

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureTestServices(services =>
{
services.RemoveAll<DbContextOptions<MyContext>>();
services.RemoveAll<MyContext>();

services.AddDbContext<MyContext>(x => x.UseNpgsql(_dbContainer.GetConnectionString()));
});
}

public async Task InitializeAsync()
{
await _dbContainer.StartAsync();

_dbConnection = new NpgsqlConnection(_dbContainer.GetConnectionString());
await _dbConnection.OpenAsync();

using var scope = Services.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<MyContext>();
await dbContext.Database.MigrateAsync();

_respawner = await Respawner.CreateAsync(_dbConnection, new RespawnerOptions
{
DbAdapter = DbAdapter.Postgres,
SchemasToInclude = ["public"]
});
}

public async Task ResetDatabaseAsync() => await _respawner.ResetAsync(_dbConnection);
public new async Task DisposeAsync() => await _dbContainer.StopAsync();
}
Want results from more Discord servers?
Add your server