Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungKI half beim Finden: iOS 27 schließt mehr als 100 Sicherheitslücken(21.09.2026 um 06:00 Uhr)
Sichere ProgrammierungWhat Is Rowhammer? How Can Repeated Memory Access Flip Bits in RAM?(21.09.2026 um 07:12 Uhr)
Sichere Programmierungnpm publish Ignores .gitignore: The .npmignore Override Rule(21.09.2026 um 07:15 Uhr)
Sichere ProgrammierungAphelion Editor - A free node-based video / VFX editor(21.09.2026 um 07:21 Uhr)
Sichere ProgrammierungGovernance Attack Surface Review: OKX(21.09.2026 um 07:31 Uhr)
Sichere ProgrammierungJSM Portal Request Create Property Panel Submit(21.09.2026 um 07:34 Uhr)
Reverse Engineeringsearch instructions assembly easy (X86,RISCV,AARCH64,etc)(20.09.2026 um 15:44 Uhr)
Sichere ProgrammierungKI half beim Finden: iOS 27 schließt mehr als 100 Sicherheitslücken(21.09.2026 um 06:00 Uhr)
Sichere ProgrammierungWhat Is Rowhammer? How Can Repeated Memory Access Flip Bits in RAM?(21.09.2026 um 07:12 Uhr)
Sichere Programmierungnpm publish Ignores .gitignore: The .npmignore Override Rule(21.09.2026 um 07:15 Uhr)
Sichere ProgrammierungAphelion Editor - A free node-based video / VFX editor(21.09.2026 um 07:21 Uhr)
Sichere ProgrammierungGovernance Attack Surface Review: OKX(21.09.2026 um 07:31 Uhr)
Sichere ProgrammierungJSM Portal Request Create Property Panel Submit(21.09.2026 um 07:34 Uhr)
Reverse Engineeringsearch instructions assembly easy (X86,RISCV,AARCH64,etc)(20.09.2026 um 15:44 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Testcontainers

Reagiere als Erste:r — dein Feedback zählt!

1. Introduction

Testing code that depends on databases and external services is difficult. Many teams rely on shared test environments or in-memory databases like H2, but both approaches are error-prone. Shared environments break due to data conflicts or configuration changes, while in-memory databases often behave differently from production systems.

Testcontainers solves this by running real dependencies inside Docker containers during tests. Each test run gets its own isolated, disposable environment that closely matches production. This is especially valuable for database integration testing, where using the actual database engine leads to more reliable tests and fewer production surprises.

2. Docker

Let’s start with a quick refresher on Docker containers. This article assumes you already have some familiarity with Docker and its core components. That said, we’ll briefly revisit the high-level concepts to align terminology and build a shared mental model before moving forward.

Docker file

A Dockerfile defines the steps required to build a Docker image. For programmers, a useful way to think about a Dockerfile is as a class definition. It acts as a template from which Docker Engine creates a Docker image, and that image can then be used to create multiple container instances, similar to creating objects from a class. Docker Engine processes the Dockerfile and builds a Docker image, which can be executed anywhere as long as the host system uses a compatible operating system kernel.

A Dockerfile allows you to:

  • Choose a base image
  • Install system packages and dependencies
  • Copy application files
  • Set environment variables and configuration
  • Expose ports
  • Define entry points

Docker Image

A Docker image is a packaged snapshot of an application and everything it needs to run, including required libraries, dependencies, and a minimal base filesystem.

Docker Engine creates the image by processing a Dockerfile. Once built, the image is immutable, meaning it never changes, and all containers created from it behave consistently.

Docker images are not heavyweight because they do not include a full operating system or kernel. Instead, they use a minimal filesystem and a layered design, where layers are shared and reused across images to keep them small and efficient.

Docker Container

A Docker container is a running instance of a Docker image, created and started by Docker Engine.

Containers provide an isolated environment for applications. Each container has its own filesystem, process space, network interfaces, and environment variables. Containers are isolated from one another, so processes in one container cannot see or interfere with processes in another.

At the same time, containers share the host operating system kernel. This shared kernel is what makes containers lightweight compared to virtual machines.

Containers are mutable at runtime, but any changes made inside a container are discarded when the container is removed unless explicitly persisted using volumes.

3. Testcontainers

How Testcontainers Works

At a high level, Testcontainers starts Docker containers as part of your test execution.

When a test begins, Testcontainers pulls the required Docker image (if it’s not already available), starts a container, and waits until the service inside the container is ready to accept connections. Your test code then connects to this container using dynamically provided hostnames, ports, and credentials.

Once the tests finish, Testcontainers automatically stops and removes the containers. This ensures each test run starts from a clean, isolated state with no leftover data or configuration.
All of this happens programmatically inside your test framework, so developers do not need to manually start databases or manage shared environments. The same tests can be run locally and in CI with consistent behavior, as long as Docker is available.

Here are some helpful Docker commands when working with Testcontainers:

# Verify Docker is running
docker info

# Pull an image manually (example: MySQL)
docker pull mysql:8.0

# List downloaded MySQL images
docker images | grep mysql

MySQL Integration Test

Gradle dependencies:

dependencies {
    testImplementation "org.junit.jupiter:junit-jupiter:5.10.1"

    // Testcontainers core + JUnit 5 support
    testImplementation "org.testcontainers:testcontainers:1.19.7"
    testImplementation "org.testcontainers:junit-jupiter:1.19.7"

    // MySQL Testcontainer
    testImplementation "org.testcontainers:mysql:1.19.7"

    // MySQL JDBC driver
    testImplementation "mysql:mysql-connector-j:8.3.0"
}

test {
    useJUnitPlatform()
}

Integration test

import org.junit.jupiter.api.Test;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import static org.junit.jupiter.api.Assertions.assertEquals;

@Testcontainers
class MySqlIT {

  @Container
  static final MySQLContainer<?> mysql =
      new MySQLContainer<>("mysql:8.0")
          .withDatabaseName("test_db")
          .withUsername("test")
          .withPassword("test");

  @Test
  void canInsertAndQuery() throws Exception {
    try (Connection conn =
             DriverManager.getConnection(mysql.getJdbcUrl(), mysql.getUsername(), mysql.getPassword());
         Statement stmt = conn.createStatement()) {

      stmt.execute("CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(100))");
      stmt.execute("INSERT INTO users (id, name) VALUES (1, 'FK')");

      try (ResultSet rs = stmt.executeQuery("SELECT name FROM users WHERE id = 1")) {
        rs.next();
        assertEquals("FK", rs.getString(1));
      }
    }
  }
}

Kafka Integration Test

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;

import java.time.Duration;
import java.util.Collections;
import java.util.Properties;

import static org.junit.jupiter.api.Assertions.assertTrue;

@Testcontainers
class KafkaIT {

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

  @Test
  void canProduceAndConsume() {
    String topic = "events";

    // Producer
    Properties producerProps = new Properties();
    producerProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafka.getBootstrapServers());
    producerProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
    producerProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

    try (KafkaProducer<String, String> producer = new KafkaProducer<>(producerProps)) {
      producer.send(new ProducerRecord<>(topic, "k1", "hello-from-testcontainers"));
      producer.flush();
    }

    // Consumer
    Properties consumerProps = new Properties();
    consumerProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafka.getBootstrapServers());
    consumerProps.put(ConsumerConfig.GROUP_ID_CONFIG, "it-group");
    consumerProps.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
    consumerProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
    consumerProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());

    try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(consumerProps)) {
      consumer.subscribe(Collections.singletonList(topic));

      boolean found = false;
      long deadlineMs = System.currentTimeMillis() + 5_000;

      while (!found && System.currentTimeMillis() < deadlineMs) {
        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(250));
        found = records.records(topic).stream()
            .anyMatch(r -> "hello-from-testcontainers".equals(r.value()));
      }

      assertTrue(found, "Expected message was not consumed within timeout");
    }
  }
}

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Testcontainers

Thematisch verwandte Begriffe: Testcontainers · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94109 | openEQUELLA versions before 2026.1.0 contain a remote code execution vul…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick