Integrationstests von Kotlin mit Docker: von A bis Z
\n\nIn der modernen Kotlin-Entwicklung sind Integrationstests mit Docker zum De-facto-Standard geworden. Die Containerisierung ermöglicht die Erstellung isolierter, reproduzierbarer Testumgebungen, die der Produktionsumgebung so nahe wie möglich kommen. In diesem Artikel werden wir den gesamten Prozess der Einrichtung und des Schreibens von Integrationstests für Kotlin-Anwendungen mit Docker und der Bibliothek Testcontainers durchgehen.
\n\nWarum ist Docker für Integrationstests von Kotlin wichtig?
\n\nTraditionelle Integrationstests leiden oft unter Umgebungsproblemen: unterschiedliche Datenbankversionen, Treiberinkompatibilitäten, "flaky" Tests aufgrund von Hintergrundprozessen. Docker löst diese Probleme, indem es Folgendes bietet:
\n\n- \n
- Isolation: jeder Test wird in einem sauberen Container ausgeführt \n
- Reproduzierbarkeit: gleiche Umgebung auf jedem Rechner \n
- Skalierbarkeit: Möglichkeit, komplexe Mikroservice-Architekturen zu testen \n
- Geschwindigkeit: schnelles Starten und Stoppen von Containern \n
Einrichtung eines Kotlin-Projekts für Integrationstests mit Docker
\n\nZunächst fügen wir die erforderlichen Abhängigkeiten in build.gradle.kts hinzu:
dependencies {\n // Testcontainers\n testImplementation("org.testcontainers:testcontainers:1.19.3")\n testImplementation("org.testcontainers:postgresql:1.19.3")\n testImplementation("org.testcontainers:kafka:1.19.3")\n testImplementation("org.testcontainers:junit-jupiter:1.19.3")\n \n // Datenbank\n testImplementation("org.postgresql:postgresql:42.7.1")\n \n // JUnit 5\n testImplementation("org.junit.jupiter:junit-jupiter:5.10.1")\n \n // Für Spring Boot Anwendungen\n testImplementation("org.springframework.boot:spring-boot-starter-test:3.2.1")\n testImplementation("org.springframework.boot:spring-boot-testcontainers:3.2.1")\n}\n\nBasisbeispiel: Testen mit PostgreSQL
\n\nBetrachten wir ein einfaches Beispiel - das Testen eines Repositorys, das mit PostgreSQL arbeitet. Erstellen wir einen Integrationstest mit Testcontainers:
\n\nimport org.junit.jupiter.api.Test\nimport org.testcontainers.containers.PostgreSQLContainer\nimport org.testcontainers.junit.jupiter.Container\nimport org.testcontainers.junit.jupiter.Testcontainers\nimport javax.sql.DataSource\n\n@Testcontainers\nclass UserRepositoryIntegrationTest {\n\n companion object {\n @Container\n val postgres = PostgreSQLContainer<Nothing>("postgres:15-alpine").apply {\n withDatabaseName("testdb")\n withUsername("test")\n withPassword("test")\n }\n }\n\n @Test\n fun `should save and find user`() {\n val dataSource = createDataSource(postgres)\n val repository = UserRepository(dataSource)\n \n val user = User(id = null, name = "Ivan Petrov", email = "ivan@example.com")\n val savedUser = repository.save(user)\n \n val foundUser = repository.findById(savedUser.id!!)\n assert(foundUser != null)\n assert(foundUser?.name == "Ivan Petrov")\n }\n\n private fun createDataSource(container: PostgreSQLContainer<*>): DataSource {\n val config = HikariConfig().apply {\n jdbcUrl = container.jdbcUrl\n username = container.username\n password = container.password\n driverClassName = container.driverClassName\n }\n return HikariDataSource(config)\n }\n}\n\nTesten von Mikroservices mit Kafka und Docker Compose
\n\nFür komplexere Szenarien, die mehrere Dienste erfordern, verwenden Sie Docker Compose über Testcontainers:
\n\nimport org.testcontainers.containers.DockerComposeContainer\nimport org.testcontainers.containers.wait.strategy.Wait\nimport java.io.File\n\nclass OrderService