Integration Testing with Testcontainers

Mocking the database in tests is a lie. In-memory databases (like EF Core InMemory) behave differently than SQL Server. **Testcontainers** allows you to spin up real, throwaway Docker containers for your integration tests.

Setup in xUnit

public class IntegrationTest : IAsyncLifetime
{
    private readonly MsSqlContainer _dbContainer = new MsSqlBuilder()
        .WithPassword("StrongP@ssw0rd!")
        .Build();

    public async Task InitializeAsync()
    {
        await _dbContainer.StartAsync();
        // Run migrations...
    }

    public async Task DisposeAsync()
    {
        await _dbContainer.StopAsync();
    }
}

Writing the Test

[Fact]
public async Task CreateOrder_ShouldPersist_ToRealSql()
{
    var options = new DbContextOptionsBuilder()
        .UseSqlServer(_dbContainer.GetConnectionString())
        .Options;

    using var context = new MyDbContext(options);
    context.Orders.Add(new Order { Total = 100 });
    await context.SaveChangesAsync();

    var saved = await context.Orders.FirstAsync();
    Assert.Equal(100, saved.Total);
}

Key Takeaways

  • Test against the exact version of the database you use in production.
  • Works for Redis, RabbitMQ, Kafka, etc.
  • Requires Docker Desktop to be running.

Discover more from C4: Container, Code, Cloud & Context

Subscribe to get the latest posts sent to your email.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.