Testcontainers for integration tests
Test against a real Postgres or Kafka in a throwaway container instead of against a mock.
Open this lesson in the learning hubKey points
- Testcontainers starts a real dependency from inside a JUnit test and hands you the random host port it landed on.
- A random port is the point: no clashes, so the same suite runs on a laptop and on a shared CI agent at the same time.
- In Spring Boot 3.1+ annotate the container
@ServiceConnectionand the datasource properties are wired for you. - Make the container
staticso it starts once per class. Container startup is the slow part, not your assertions. - The Ryuk sidecar removes the containers when the JVM exits, even after a crash, so nothing is left behind on the agent.
- The one real prerequisite is a reachable Docker daemon on whatever machine runs the tests.
Example
@SpringBootTest
@Testcontainers
class OrderRepositoryTest {
// static: started once for the whole class, not per test method
@Container
@ServiceConnection
static PostgreSQLContainer<?> db = new PostgreSQLContainer<>("postgres:16-alpine");
@Autowired OrderRepository repo;
@Test
void savesAndReadsBack() {
repo.save(new Order("A-1", 3));
assertThat(repo.findByRef("A-1")).isPresent();
}
}
// no jdbc url, user or password anywhere: @ServiceConnection supplies them
A real database in the test beats a mock that agrees with you.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Docker course, and every lesson in it is listed on the Docker contents page.