| name | Docker Testcontainers |
| description | Integration testing with real dependencies in throwaway Docker containers using the Testcontainers Node.js API - GenericContainer, exposed ports, wait strategies, module containers, Docker Compose environments, and reliable cleanup. |
| version | 1.0.0 |
| author | thetestingacademy |
| license | MIT |
| tags | ["testcontainers","docker","integration-testing","postgres","redis","containers","ci","node"] |
| testingTypes | ["integration","database"] |
| frameworks | ["jest","vitest"] |
| languages | ["typescript"] |
| domains | ["api","devops"] |
| agents | ["claude-code","cursor","github-copilot","windsurf","codex","aider","continue","cline","zed","bolt","gemini-cli","amp"] |
Docker Testcontainers
This skill makes an AI agent write integration tests that spin up real databases, caches, and message brokers in disposable Docker containers via the testcontainers Node.js library - instead of mocking them or depending on a shared dev server. Trigger it when tests need a real Postgres, Redis, Kafka, or any service with Docker image, when a repo already imports testcontainers, or when the user complains that mocked repositories keep hiding SQL and serialization bugs.
Core Principles
- Test against the real engine, not a lookalike. SQLite in place of Postgres misses JSONB operators, transaction isolation behavior, and case-sensitivity rules. Run the exact image and major version production uses (
postgres:16-alpine, not latest).
- Always use mapped ports. Containers bind to random free host ports. Read them with
container.getMappedPort(5432) and container.getHost(); hardcoding localhost:5432 collides with local services and parallel CI jobs.
- Wait strategies, not sleeps. A started container is not a ready service. Use
Wait.forLogMessage, Wait.forListeningPorts, Wait.forHttp, or Wait.forHealthCheck so tests begin exactly when the dependency is usable.
- One container per suite, clean state per test. Container startup costs seconds; start in
beforeAll, then reset state between tests with TRUNCATE, FLUSHALL, or transaction rollbacks - not by restarting the container.
- Cleanup must survive failures. Stop containers in
afterAll; Testcontainers' Ryuk sidecar reaps anything left behind if the process dies, so never disable it in CI.
- Pin image tags.
redis:latest changing under you turns a green suite red with zero code changes. Pin to a major-minor tag and upgrade deliberately.
Setup
npm install --save-dev testcontainers @testcontainers/postgresql
docker info
Patterns
1. GenericContainer: Redis with a wait strategy
import { , , } ;
{ createClient, } ;
(, {
: ;
: ;
( () => {
container = ()
.()
.(.())
.()
.();
client = ({
: ,
});
client.();
}, );
( () => {
client.();
});
( () => {
client.();
container.();
});
(, () => {
( i = ; i < ; i++) {
( (client, )).();
}
( (client, )).();
});
});
(): <> {
count = client.();
(count === ) client.(, );
count <= ;
}