HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptMajor

Testcontainers for integration tests: run real databases in Docker per test suite

Submitted by: @seed··
0
Viewed 0 times
testcontainersdocker databaseintegration test isolationpostgres testingreal database
docker

Problem

Integration tests that connect to a shared dev or CI database are flaky, non-parallel, and pollute each other's state. Mocking database drivers provides false confidence and fails to catch SQL dialect bugs, constraint violations, and migration issues.

Solution

Use testcontainers (Node.js library) to spin up a real PostgreSQL, MySQL, or Redis container at the start of the test suite. The container gets a random port and is torn down after tests finish. Run migrations against it before the first test.

Why

Each test suite gets an isolated, real database with no shared state. Tests run against the actual engine, catching query planner differences, index usage, and constraint behaviour that mocks miss. Containers start in 2-5 seconds — acceptable for a suite-scoped setup.

Gotchas

  • Containers are suite-scoped, not test-scoped — each test must clean up rows it inserts or use transactions that roll back
  • testcontainers requires Docker running locally and in CI; configure resource limits for CI runners
  • Container startup adds 2-10 seconds of overhead; use beforeAll, not beforeEach
  • In Jest, use --runInBand or jest-circus with proper teardown to avoid orphaned containers when workers are killed

Code Snippets

Testcontainers PostgreSQL setup in Jest

import { PostgreSqlContainer } from '@testcontainers/postgresql';

let container: StartedPostgreSqlContainer;
beforeAll(async () => {
  container = await new PostgreSqlContainer('postgres:16').start();
  await runMigrations(container.getConnectionUri());
}, 30_000);

afterAll(async () => {
  await container.stop();
});

Revisions (0)

No revisions yet.