Zum Inhalt

_

_ _

_

TestContainer Cheatsheet

• Installation

Prerequisiten

Requirement Version Verification Command
Docker Latest stable INLINE_CODE_12
Java JDK 8 or higher INLINE_CODE_13
Maven/Gradle Latest INLINE_CODE_14 or INLINE_CODE_15

Maven Dependances

<!-- Core TestContainers -->
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>1.19.3</version>
    <scope>test</scope>
</dependency>

<!-- JUnit 5 Integration -->
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>1.19.3</version>
    <scope>test</scope>
</dependency>

<!-- Database Modules -->
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <version>1.19.3</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>mysql</artifactId>
    <version>1.19.3</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>mongodb</artifactId>
    <version>1.19.3</version>
    <scope>test</scope>
</dependency>

Gradle Dependances

// Kotlin DSL
testImplementation("org.testcontainers:testcontainers:1.19.3")
testImplementation("org.testcontainers:junit-jupiter:1.19.3")
testImplementation("org.testcontainers:postgresql:1.19.3")
testImplementation("org.testcontainers:mysql:1.19.3")
testImplementation("org.testcontainers:kafka:1.19.3")
// Groovy DSL
testImplementation 'org.testcontainers:testcontainers:1.19.3'
testImplementation 'org.testcontainers:junit-jupiter:1.19.3'
testImplementation 'org.testcontainers:postgresql:1.19.3'

Docker Setup by Platform

Platform Installation Command
Ubuntu/Debian INLINE_CODE_16
macOS INLINE_CODE_17
Windows Download Docker Desktop from docker.com
Linux Post-Install INLINE_CODE_18
_
oder Grundlegende Befehle

Container Lifecycle Operations

Command Description
INLINE_CODE_19 Start a container instance
INLINE_CODE_20 Stop and remove the container
INLINE_CODE_21 Check if container is currently running
INLINE_CODE_22 Get Docker container ID
INLINE_CODE_23 Get the image name used
INLINE_CODE_24 Retrieve all container logs as string
INLINE_CODE_25 Get host address (usually localhost)
INLINE_CODE_26 Get host port mapped to container port
INLINE_CODE_27 List all exposed container ports
INLINE_CODE_28 Get detailed container information
_
### Generische Container-Erstellung
Command Description
INLINE_CODE_29 Create container from any Docker image
INLINE_CODE_30 Expose container ports to host
INLINE_CODE_31 Set environment variable
INLINE_CODE_32 Override container command
INLINE_CODE_33 Add Docker label to container
INLINE_CODE_34 Set container network mode
INLINE_CODE_35 Run container in privileged mode
INLINE_CODE_36 Modify container creation command
INLINE_CODE_37 Set maximum startup wait time
INLINE_CODE_38 Enable container reuse across tests
_
### Datenbank Container
Command Description
INLINE_CODE_39 Create PostgreSQL container
INLINE_CODE_40 Create MySQL container
INLINE_CODE_41 Create MongoDB container
INLINE_CODE_42 Set database name
INLINE_CODE_43 Set database username
INLINE_CODE_44 Set database password
INLINE_CODE_45 Get JDBC connection URL
INLINE_CODE_46 Get MongoDB replica set URL (MongoDB)
INLINE_CODE_47 Run SQL script on startup
INLINE_CODE_48 Override database configuration
_
/ Fortgeschrittene Nutzung

Wait Strategies

Command Description
INLINE_CODE_49 Wait until port is listening
INLINE_CODE_50 Wait for HTTP endpoint to respond
INLINE_CODE_51 Wait for specific log message
INLINE_CODE_52 Wait for Docker healthcheck to pass
INLINE_CODE_53 Wait for command to succeed
INLINE_CODE_54 Specify expected HTTP status code
INLINE_CODE_55 Custom status code matcher
INLINE_CODE_56 Set startup timeout duration
INLINE_CODE_57 Set HTTP read timeout
INLINE_CODE_58 Custom response validation

File and Volume Operations

Command Description
INLINE_CODE_59 Bind mount host directory
INLINE_CODE_60 Mount with specific mode
INLINE_CODE_61 Mount classpath resource
INLINE_CODE_62 Copy file into container
INLINE_CODE_63 Copy file during startup
INLINE_CODE_64 Mount tmpfs filesystem
INLINE_CODE_65 Reference classpath file
INLINE_CODE_66 Reference host file system path
INLINE_CODE_67 Allow read and write access
INLINE_CODE_68 Allow only read access

Networking

Command Description
INLINE_CODE_69 Create custom Docker network
INLINE_CODE_70 Attach container to network
INLINE_CODE_71 Set network alias for container
INLINE_CODE_72 Define container dependency
INLINE_CODE_73 Add entry to /etc/hosts
INLINE_CODE_74 Get all network aliases
INLINE_CODE_75 Allow container to access host
INLINE_CODE_76 Use shared network across tests
INLINE_CODE_77 Set specific network mode
INLINE_CODE_78 Get network container is attached to

Container Execution

Command Description
INLINE_CODE_79 Execute command in running container
INLINE_CODE_80 Execute with specific charset
INLINE_CODE_81 Get standard output from execution
INLINE_CODE_82 Get standard error from execution
INLINE_CODE_83 Get command exit code
INLINE_CODE_84 Copy file from container
INLINE_CODE_85 Stream container logs
INLINE_CODE_86 Log output to SLF4J logger
INLINE_CODE_87 Capture output as string
INLINE_CODE_88 Wait for specific output

JUnit 5 Integration

Command Description
INLINE_CODE_89 Enable TestContainers extension
INLINE_CODE_90 Mark field as container to manage
INLINE_CODE_91 Share container across all tests
INLINE_CODE_92 Inject container properties
INLINE_CODE_93 Add dynamic property
INLINE_CODE_94 Setup containers before all tests
INLINE_CODE_95 Cleanup containers after all tests
INLINE_CODE_96 Group tests with shared containers
INLINE_CODE_97 Start multiple containers in parallel
INLINE_CODE_98 Reuse container across test runs
_
Konfiguration

TestContainer Eigenschaften

Erstellen testcontainers.properties in src/test/resources:

# Docker host configuration
docker.host=unix:///var/run/docker.sock
# docker.host=tcp://localhost:2375

# Container reuse (requires Docker labels support)
testcontainers.reuse.enable=true

# Image pull policy
testcontainers.image.pull.policy=DefaultPullPolicy

# Ryuk container (cleanup)
testcontainers.ryuk.disabled=false
testcontainers.ryuk.container.image=testcontainers/ryuk:0.5.1

# Checks
testcontainers.checks.disable=false

Docker Compose Integration

@Container
static DockerComposeContainer environment = 
    new DockerComposeContainer(new File("docker-compose.yml"))
        .withExposedService("db", 5432)
        .withExposedService("redis", 6379)
        .withLocalCompose(true)
        .withPull(true)
        .waitingFor("db", Wait.forHealthcheck());

Individuelle Containerkonfiguration

public class CustomPostgreSQLContainer extends PostgreSQLContainer<CustomPostgreSQLContainer> {
    private static final String IMAGE_VERSION = "postgres:15-alpine";

    public CustomPostgreSQLContainer() {
        super(IMAGE_VERSION);
        this.withDatabaseName("testdb")
            .withUsername("testuser")
            .withPassword("testpass")
            .withInitScript("init.sql")
            .withCommand("postgres -c max_connections=200");
    }
}

Spring Boot Integration

@SpringBootTest
@Testcontainers
class ApplicationTests {

    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15-alpine")
        .withDatabaseName("testdb");

    @DynamicPropertySource
    static void configureProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
        registry.add("spring.jpa.hibernate.ddl-auto", () -> "create-drop");
    }

    @Test
    void contextLoads() {
        // Test with real database
    }
}

Häufige Anwendungsfälle

Use Case 1: PostgreSQL Integration Test

@Testcontainers
@SpringBootTest
class UserRepositoryTest {

    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15-alpine")
        .withDatabaseName("testdb")
        .withUsername("test")
        .withPassword("test")
        .withInitScript("schema.sql");

    @DynamicPropertySource
    static void registerProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", postgres::getJdbcUrl);
        registry.add("spring.datasource.username", postgres::getUsername);
        registry.add("spring.datasource.password", postgres::getPassword);
    }

    @Autowired
    private UserRepository userRepository;

    @Test
    void shouldSaveAndFindUser() {
        User user = new User("john@example.com", "John Doe");
        userRepository.save(user);

        Optional<User> found = userRepository.findByEmail("john@example.com");
        assertTrue(found.isPresent());
        assertEquals("John Doe", found.get().getName());
    }
}

Use Case 2: Kafka Message Processing Test

@Testcontainers
class KafkaIntegrationTest {

    @Container
    static KafkaContainer kafka = new KafkaContainer(
        DockerImageName.parse("confluentinc/cp-kafka:7.5.0")
    );

    @DynamicPropertySource
    static void kafkaProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.kafka.bootstrap-servers", kafka::getBootstrapServers);
    }

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Autowired
    private MessageListener messageListener;

    @Test
    void shouldProcessMessage() throws Exception {
        String topic = "test-topic";
        String message = "Hello Kafka!";

        kafkaTemplate.send(topic, message);

        // Wait for message processing
        await().atMost(Duration.ofSeconds(10))
               .until(() -> messageListener.getReceivedMessages().size() == 1);

        assertEquals(message, messageListener.getReceivedMessages().get(0));
    }
}

Use Case 3: Multi-Container Mikroservices Prüfverfahren

@Testcontainers
class MicroservicesIntegrationTest {

    static Network network = Network.newNetwork();

    @Container
    static PostgreSQLContainer<?> database = new PostgreSQLContainer<>("postgres:15-alpine")
        .withNetwork(network)
        .withNetworkAliases("database")
        .withDatabaseName("orders");

    @Container
    static GenericContainer<?> redis = new GenericContainer<>("redis:7-alpine")
        .withNetwork(network)
        .withNetworkAliases("redis")
        .withExposedPorts(6379);

    @Container
    static GenericContainer<?> orderService = new GenericContainer<>("order-service:latest")
        .withNetwork(network)
        .withExposedPorts(8080)
        .withEnv("DATABASE_URL", "jdbc:postgresql://database:5432/orders")
        .withEnv("REDIS_HOST", "redis")
        .dependsOn(database, redis)
        .waitingFor(Wait.forHttp("/actuator/health").forStatusCode(200));

    @Test
    void shouldCreateOrder() {
        String baseUrl = "http://" + orderService.getHost() + ":" 
                       + orderService.getMappedPort(8080);

        // Make HTTP request to order service
        RestTemplate restTemplate = new RestTemplate();
        Order order = new Order("item-123", 2);

        ResponseEntity<Order> response = restTemplate.postForEntity(
            baseUrl + "/orders", order, Order.class
        );

        assertEquals(HttpStatus.CREATED, response.getStatusCode());
        assertNotNull(response.getBody().getId());
    }
}

Use Case 4: MongoDB Integration Prüfverfahren

@Testcontainers
@DataMongoTest
class ProductRepositoryTest {

    @Container
    static MongoDBContainer mongodb = new MongoDBContainer("mongo:6.0")
        .withExposedPorts(27017);

    @DynamicPropertySource
    static void mongoProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.mongodb.uri", mongodb::getReplicaSetUrl);
    }

    @Autowired
    private ProductRepository productRepository;

    @Test
    void shouldFindProductsByCategory() {
        // Insert test data
        productRepository.save(new Product("Laptop", "Electronics", 999.99));
        productRepository.save(new Product("Mouse", "Electronics", 29.99));
        productRepository.save(new Product("Desk", "Furniture", 299.99));

        // Query by category
        List<Product> electronics = productRepository.findByCategory("Electronics");

        assertEquals(2, electronics.size());
        assertTrue(electronics.stream()
                  .allMatch(p -> p.getCategory().equals("Electronics")));
    }
}

Use Case 5: Docker Compose Test Environment

@Testcontainers
class FullStackIntegrationTest {

    @Container
    static DockerComposeContainer<?> environment = new DockerComposeContainer<>(
        new File("src/test/resources/docker-compose-test.yml")
    )
        .withExposedService("api", 8080, 
            Wait.forHttp("/health").forStatusCode(200))
        .withExposedService("postgres", 5432, 
            Wait.forListeningPort())
        .withExposedService("redis", 6379)
        .withLocalCompose(true);

    @Test
    void shouldConnectToAllServices() {
        String apiHost = environment.getServiceHost("api", 8080);
        Integer apiPort = environment.getServicePort("api", 8080);

        String apiUrl = "http://" + apiHost + ":" + apiPort;

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.getForEntity(
            apiUrl + "/health", String.class
        );

        assertEquals(HttpStatus.OK, response.getStatusCode());
    }
}

oder Best Practices

Container Management

** Verwenden Sie statische Behälter für Prüfklassen*: Teilen Sie Container über alle Testmethoden, um Startzeit und Ressourcennutzung zu reduzieren - Umsetzen von Containern*: Aktivieren testcontainers.reuse.enable=true für schnellere lokale Entwicklungstestzyklen - ** Mittel aufstocken Verwenden Sie __INLINE_CODE_102_ oder versuchen Sie mit Ressourcen, wenn Sie Behälter außerhalb der JUnit Integration manuell verwalten - **Benutzen Sie spezifische Bild-Tags*: Vermeiden Sie latest Tag; verwenden Sie spezifische Versionen wie postgres:15-alpine für reproduzierbare Tests

Leistungsoptimierung

  • **Parallel Container-Start*: Verwenden Sie Startables.deepStart(), um mehrere unabhängige Behälter gleichzeitig zu starten
  • **Minimize Container Neustarts*: Verwenden Sie class-level __INLINE_CODE_106_ anstelle von method-level, wenn möglich
  • **Wählen Sie leichte Bilder*: Vorziehen Sie alpenbasierte Bilder (z.B. postgres:15-alpine) um Zugzeit und Festplattennutzung zu reduzieren
  • **Wettbewerbsstrategien sinnvoll*: Verwenden Sie geeignete Wartestrategien, um unnötige Verzögerungen zu vermeiden, während Behälterbereitschaft

Testing Strategy

  • **Test gegen produktionsähnliche Abhängigkeiten*: Verwenden Sie echte Datenbank-Engines und Nachrichtenbroker anstelle von eingebetteten Versionen
  • **Isolate Testdaten*: Stellen Sie sicher, dass jeder Test eigene Daten erstellt und reinigt, um Testinterdependien zu verhindern
  • ** Verwenden Sie Netzwerk-Aliases*: Erstellen Sie benutzerdefinierte Netzwerke und verwenden Sie aussagekräftige Alias für die intercontainer Kommunikation
  • Implementierung von Gesundheitskontrollen Konfigurieren Sie immer richtige Wartestrategien, um sicherzustellen, dass die Behälter vollständig bereit sind, bevor die Tests durchgeführt werden

CI/CD Integration

  • **Verify Docker Verfügbarkeit*: Stellen Sie sicher, dass die CI Umgebung Docker installiert und zugänglich ist
  • **Konfigurieren Sie Timeouts entsprechend*: Stellen Sie realistische Startup-Timeouts unter Berücksichtigung der CI-Umgebung Leistung
  • Benutzen Sie Bild caching: Konfigurieren Sie CI, um Docker-Bilder zu kachen, um nachfolgende Abläufe zu beschleunigen
  • **Monitor Ressourcennutzung*: Beachten Sie die Speicher- und CPU-Grenzwerte in CI-Umgebungen; passen Sie die Containerkonfigurationen entsprechend an

Sicherheit und Wartung

  • **Keep TestContainers aktualisiert*: Aktualisieren Sie regelmäßig auf neueste Versionen für Sicherheitspatches und neue Features
  • Beamte Bilder: Offizielle Docker Bilder von verifizierten Verlegern vorziehen **Avoid privilegierter Modus*: Nur verwenden .withPrivilegedMode(), wenn unbedingt notwendig
  • **Belichtete Ports anzeigen* Nur aussetzen Ports, die tatsächlich für Tests benötigt werden

Fehlerbehebung

Issue Solution
Container fails to start: "Cannot connect to Docker daemon" Ensure Docker is running: INLINE_CODE_109. On Linux, add user to docker group: INLINE_CODE_110
Tests timeout during container startup Increase timeout: INLINE_CODE_111 or check Docker resources (CPU/Memory)
Port binding conflicts: "Address already in use" Use dynamic ports: INLINE_CODE_112 instead of fixed ports, or stop conflicting services
Image pull fails: "manifest unknown" Verify image name and tag exist on Docker Hub. Use specific tags instead of INLINE_CODE_113
Container starts but tests fail to connect Check wait strategy is appropriate: add INLINE_CODE_114 or INLINE_CODE_115
Out of memory errors during tests Reduce number of parallel containers, increase Docker memory limit in Docker Desktop settings, or use INLINE_CODE_116
"Ryuk container not found" warnings Disable Ryuk if needed: set INLINE_CODE_117 in properties (not recommended for production)
Tests work locally but fail in CI Ensure CI has Docker installed, check timeout settings, verify network connectivity, review CI environment resource limits
Database connection refused Wait for database to be ready: use INLINE_CODE_118 and verify JDBC URL with INLINE_CODE_119
Container logs show errors but tests pass Enable log following: INLINE_CODE_120 to debug container issues
Slow test execution Use container reuse, share containers at class level, start containers in parallel with INLINE_CODE_121
"No such file or directory" when mounting volumes Use absolute paths or INLINE_CODE_122 for classpath resources
Network communication between containers fails Create custom network: INLINE_CODE_123 and attach containers with INLINE_CODE_124 and INLINE_CODE_125
TestContainers properties not being read Ensure INLINE_CODE_126 is in INLINE_CODE_127 and properly formatted
Container cleanup not happening Check Ryuk container is running: INLINE_CODE_128. Ensure tests complete normally without hanging
_
Verfügbare Module
Module Maven Artifact Description
PostgreSQL INLINE_CODE_129 PostgreSQL database containers
MySQL INLINE_CODE_130 MySQL database containers
MongoDB INLINE_CODE_131 MongoDB document database
Kafka INLINE_CODE_132 Apache Kafka message broker
Redis INLINE_CODE_133 Redis in-memory data store
Elasticsearch INLINE_CODE_134 Elasticsearch search engine
Cassandra INLINE_CODE_135 Cassandra NoSQL database
RabbitMQ INLINE_CODE_136 RabbitMQ message broker
Selenium INLINE_CODE_137 Browser automation containers
LocalStack INLINE_CODE_138 AWS services emulation
Nginx