Testcontainers

Language: Java

Testing

Testcontainers was created to simplify integration testing by providing real, isolated environments using Docker containers. It eliminates the need for complex local setup and ensures tests run consistently across different machines and CI environments.

Testcontainers is a Java library that provides lightweight, disposable Docker containers for running integration tests. It allows developers to test against databases, message brokers, or any containerized service in a reproducible way.

Installation

maven: Add org.testcontainers:testcontainers dependency in pom.xml
gradle: Add testImplementation 'org.testcontainers:testcontainers:1.20.3' in build.gradle

Usage

Testcontainers allows developers to spin up Docker containers for databases, message queues, or other services during test execution. It supports JUnit 5 extensions, lifecycle management, reusable containers, and pre-configured modules for common services like PostgreSQL, MySQL, Kafka, and Redis.

Starting a PostgreSQL container

import org.testcontainers.containers.PostgreSQLContainer;

PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.3")
    .withDatabaseName("testdb")
    .withUsername("user")
    .withPassword("password");
postgres.start();

Starts a PostgreSQL container with a database name, username, and password for integration testing.

Using container JDBC URL

String jdbcUrl = postgres.getJdbcUrl();
String username = postgres.getUsername();
String password = postgres.getPassword();
Connection conn = DriverManager.getConnection(jdbcUrl, username, password);

Retrieves connection details from the container to connect your application to the test database.

JUnit 5 integration with @Testcontainers and @Container

import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
public class MyDatabaseTest {

    @Container
    public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15.3");

    @Test
    void testDatabaseConnection() {
        assertNotNull(postgres.getJdbcUrl());
    }
}

Uses annotations to automatically manage container lifecycle with JUnit 5 tests.

Reusable containers

postgres.withReuse(true);
// container can be reused across multiple test runs for faster execution

Enables container reuse to reduce startup time during repeated test executions.

Using Testcontainers for Kafka

import org.testcontainers.containers.KafkaContainer;
KafkaContainer kafka = new KafkaContainer("confluentinc/cp-kafka:7.6.1");
kafka.start();

Starts a Kafka container for testing messaging functionality in applications.

Custom container configuration

postgres.withInitScript("init.sql").withExposedPorts(5432);

Demonstrates how to initialize a container with a custom SQL script and expose ports.

Error Handling

Docker not found: Ensure Docker is installed and running on your system before running Testcontainers.
Container startup timeout: Increase startup timeout or verify the Docker image is available and compatible.
Networking issues connecting to container: Check Docker network configuration and exposed ports; ensure the test code uses the container's dynamic ports.

Best Practices

Use `@Testcontainers` and `@Container` annotations for automatic lifecycle management.

Prefer lightweight containers for faster test execution.

Reuse containers when possible to reduce startup time.

Externalize configuration and credentials to environment variables for security.

Combine Testcontainers with JUnit 5 for seamless integration testing in CI/CD pipelines.