Integrationstests von Kotlin mit Docker: Schritt-für-Schritt-Anleitung

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

Einleitung: Warum Integrationstests mit Docker?



Bei der Entwicklung moderner Anwendungen in Kotlin, insbesondere von Microservices, ist es wichtig zu überprüfen, wie die Komponenten des Systems miteinander und mit externen Abhängigkeiten (Datenbanken, Message Queues, Caches) interagieren. Unit-Tests isolieren den Code, garantieren aber nicht, dass die Anwendung in der realen Umgebung korrekt funktioniert.



Integrationstests mit Docker lösen dieses Problem. Docker ermöglicht es, isolierte Container mit den erforderlichen Diensten (PostgreSQL, Redis, Kafka) direkt vor dem Start der Tests hochzufahren und nach Abschluss automatisch zu zerstören. Dies bietet:



  • Reproduzierbarkeit: Tests werden immer in derselben Umgebung ausgeführt.
  • Isolation: Container beeinflussen die lokale Entwicklungsumgebung nicht.
  • Geschwindigkeit: Container starten in Sekunden, nicht Minuten.


In diesem Artikel werden wir durchgehen, wie man Integrationstests für eine Kotlin-Anwendung mit Docker, der Bibliothek Testcontainers und Docker Compose einrichtet. Sie erhalten fertige Codebeispiele und Best Practices.



1. Einrichtung des Kotlin-Projekts für Integrationstests



1.1. Abhängigkeiten in build.gradle.kts



Fügen Sie zunächst die erforderlichen Abhängigkeiten zu Ihrer build.gradle.kts-Datei hinzu. Wir werden JUnit 5, Testcontainers und den Treiber für PostgreSQL verwenden:



dependencies {    // Hauptabhängigkeiten der Anwendung    implementation("org.jetbrains.kotlin:kotlin-stdlib")    implementation("org.postgresql:postgresql:42.7.1")

// Testen testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") testImplementation("org.testcontainers:testcontainers:1.19.3") testImplementation("org.testcontainers:postgresql:1.19.3") testImplementation("org.testcontainers:junit-jupiter:1.19.3")}

tasks.test { useJUnitPlatform()}


1.2. Grundlegende Struktur der Testklasse



Erstellen wir eine einfache Klasse für den Integrationstest, die einen PostgreSQL-Container hochfährt:



import org.junit.jupiter.api.Testimport org.testcontainers.containers.PostgreSQLContainerimport org.testcontainers.junit.jupiter.Containerimport org.testcontainers.junit.jupiter.Testcontainersimport java.sql.DriverManager

@Testcontainersclass UserRepositoryIntegrationTest {

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

@Test fun `should connect to database and execute query`() { val jdbcUrl = postgres.jdbcUrl val username = postgres.username val password = postgres.password

val connection = DriverManager.getConnection(jdbcUrl, username, password) val statement = connection.createStatement()

statement.execute("CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name VARCHAR(100))") statement.execute("INSERT INTO users (name) VALUES ('Alice')")

val resultSet = statement.executeQuery("SELECT COUNT(*) FROM users") resultSet.next() val count = resultSet.getInt(1)

assert(count == 1) println("Test bestanden: $count Benutzer gefunden") }}


Beachten Sie: Die Annotation @Testcontainers verwaltet automatisch den Lebenszyklus des Containers. Er wird vor allen Tests in der Klasse gestartet und nach deren Abschluss gestoppt.



2. Testen mit mehreren Containern (Docker Compose)



In realen Projekten werden oft mehrere Dienste gleichzeitig benötigt: Datenbank, Redis, Kafka. Testcontainers unterstützt Docker Compose, was es ermöglicht, die gesamte Infrastruktur in einer Datei zu beschreiben.

Blogs

Buchempfehlungen