Integrationstests von Kotlin mit Docker: Fortgeschrittenes Niveau

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Integrationstests von Kotlin mit Docker: Fortgeschrittenes Niveau



Integrationstests sind ein entscheidender Schritt zur Überprüfung der Interaktion von Anwendungskomponenten. Im Ökosystem von Kotlin und Docker erreicht dieser Prozess durch Containerisierung eine neue Ebene. In diesem Artikel werden wir fortgeschrittene Techniken zur Einrichtung und Durchführung von Integrationstests mit Docker, Testcontainers und Kotlin DSL behandeln.



1. Grundlagen: Testcontainers mit Kotlin DSL

Testcontainers ist eine Bibliothek für Java/Kotlin, die den Lebenszyklus von Docker-Containern innerhalb von Tests verwaltet. Für Kotlin ist ein praktischer DSL verfügbar, der die Konfiguration vereinfacht.



// build.gradle.ktsdependencies {    testImplementation("org.testcontainers:testcontainers:1.20.0")    testImplementation("org.testcontainers:postgresql:1.20.0")    testImplementation("org.jetbrains.kotlin:kotlin-test")}


Beispiel eines Tests mit PostgreSQL:

import org.testcontainers.containers.PostgreSQLContainerimport org.testcontainers.junit.jupiter.Containerimport org.testcontainers.junit.jupiter.Testcontainersimport org.junit.jupiter.api.Test

@Testcontainersclass UserRepositoryTest {

companion object { @Container val postgres = PostgreSQLContainer<Nothing>("postgres:15-alpine") .withDatabaseName("testdb") .withUsername("test") .withPassword("test") }

@Test fun `should connect to database`() { val jdbcUrl = postgres.jdbcUrl // Verwenden jdbcUrl in DataSource println("Connected to: $jdbcUrl") }}


2. Paralleler Start von Containern

Um Tests zu beschleunigen, können Container parallel gestartet werden. Es ist jedoch wichtig, Portkonflikte zu berücksichtigen. Verwenden Sie dynamische Ports und Synchronisation über GenericContainer.



import org.testcontainers.containers.GenericContainerimport org.testcontainers.containers.Networkimport org.testcontainers.containers.wait.strategy.Waitimport java.time.Duration

class ParallelContainerTest {

companion object { private val network = Network.newNetwork()

private val redis1 = GenericContainer<Nothing>("redis:7-alpine") .withNetwork(network) .withNetworkAliases("redis1") .withExposedPorts(6379) .waitingFor(Wait.forListeningPort())

private val redis2 = GenericContainer<Nothing>("redis:7-alpine") .withNetwork(network) .withNetworkAliases("redis2") .withExposedPorts(6379) .waitingFor(Wait.forListeningPort())

init { redis1.start() redis2.start() } }

@Test fun `parallel containers test`() { val port1 = redis1.getMappedPort(6379) val port2 = redis2.getMappedPort(6379) println("Redis1 port: $port1, Redis2 port: $port2") }}


Verwenden Sie Network zur Isolierung und waitingFor, um auf die Bereitschaft des Containers zu warten.



3. Docker Compose in Tests

Für komplexe Szenarien (Datenbank + Nachrichtenbroker + Cache) ist die Verwendung von DockerComposeContainer praktisch. Er lädt docker-compose.yml und verwaltet alle Dienste.



import org.testcontainers.containers.DockerComposeContainerimport java.io.File

class FullStackTest {

companion object { private val compose = DockerComposeContainer<Nothing>( File("src/test/resources/docker-compose.yml") ).apply { withExposedService("postgres_1", 5432) withExposedService("redis_1", 6379) withLocalCompose(true) start() } }

@Test fun `full integration test`() { val pgPort = compose.getServicePort("postgres_1", 5432) val redisPort = compose.getServicePort

Blogs

Buchempfehlungen