Testen in Kotlin: Unit-, Integrations- und E2E-Tests von A bis Z

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

Testen in Kotlin: Unit-, Integrations- und E2E-Tests von A bis Z

\n\n

Moderne Entwicklung mit Kotlin erfordert einen systematischen Ansatz zum Testen. Unabhängig davon, ob Sie ein Backend mit Ktor oder eine mobile App für Android schreiben, ist eine qualitativ hochwertige Testabdeckung der Schlüssel zur Stabilität und Vorhersagbarkeit des Projekts. In diesem Artikel behandeln wir drei Testebenen: Modultests (Unit), Integrationstests (Integration) und End-to-End-Tests (E2E). Sie erfahren, welche Tools Sie verwenden, wie Sie effektive Tests in Kotlin schreiben und typische Fehler vermeiden.

\n\n

1. Unit-Tests in Kotlin: Die Grundlage

\n\n

Unit-Tests überprüfen die Funktionalität einzelner Funktionen, Klassen oder Methoden isoliert von externen Abhängigkeiten. In Kotlin wird dafür am häufigsten das Framework JUnit 5 in Kombination mit der Mocking-Bibliothek MockK verwendet.

\n\n

Projektkonfiguration

\n\n

Fügen Sie die Abhängigkeiten in build.gradle.kts hinzu:

\n\n
dependencies {\n    testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")\n    testImplementation("io.mockk:mockk:1.13.8")\n}\n
\n\n

Beispiel eines Unit-Tests

\n\n

Angenommen, wir haben einen einfachen Dienst zur Berechnung von Rabatten:

\n\n
class DiscountService {\n    fun applyDiscount(price: Double, discountPercent: Int): Double {\n        require(discountPercent in 0..100) { "Der Rabattprozentsatz muss zwischen 0 und 100 liegen" }\n        return price * (100 - discountPercent) / 100\n    }\n}\n
\n\n

Test für diesen Dienst:

\n\n
import org.junit.jupiter.api.Assertions.*\nimport org.junit.jupiter.api.Test\nimport org.junit.jupiter.api.assertThrows\n\nclass DiscountServiceTest {\n\n    private val service = DiscountService()\n\n    @Test\n    fun `applyDiscount berechnet korrekt 50 Prozent Rabatt`() {\n        val result = service.applyDiscount(1000.0, 50)\n        assertEquals(500.0, result, 0.001)\n    }\n\n    @Test\n    fun `applyDiscount wirft Exception bei falschem Prozentsatz`() {\n        assertThrows<IllegalArgumentException> {\n            service.applyDiscount(100.0, 150)\n        }\n    }\n}\n
\n\n

Tipp: Verwenden Sie assertThrows zum Überprüfen von Ausnahmen und benennen Sie Tests mit verständlichen Zeichenketten – das verbessert die Lesbarkeit der Berichte.

\n\n

Mocking mit MockK

\n\n

Wenn Ihre Klasse von anderen Komponenten abhängt (z. B. einem Repository oder einer API), verwenden Sie Mocks:

\n\n
class OrderService(private val paymentGateway: PaymentGateway) {\n    fun processOrder(amount: Double): String {\n        if (paymentGateway.charge(amount)) {\n            return "Erfolgreich bezahlt"\n        }\n        return "Zahlungsfehler"\n    }\n}\n\n// Test\n@Test\nfun `processOrder gibt Erfolg bei erfolgreicher Zahlung zurück`() {\n    val mockGateway = mockk<PaymentGateway>()\n    every { mockGateway.charge(any()) } returns true\n\n    val service = OrderService(mockGateway)\n    val result = service.processOrder(500.0)\n\n    assertEquals("Erfolgreich bezahlt", result)\n    verify { mockGateway.charge(500.0) }\n}\n
\n\n

2. Integrationstests: Überprüfung der Komponenteninteraktion

\n\n

Integrationstests überprüfen, wie verschiedene Teile des Systems zusammenarbeiten: Datenbank, externe APIs, Dateisystem. Für Kotlin eignet sich Testcontainers hervorragend – eine Bibliothek zum Starten von Docker-Containern während der Tests.

\n\n

Beispiel mit PostgreSQL-Datenbank

\n\n

Fügen Sie die Abhängigkeiten hinzu:

\n\n
testImplementation("org.testcontainers:testcontainers:1.19.3")\ntestImplementation("org.testcontainers:postgresql:1.19.3")\n
\n\n

Schreiben wir einen Test für die DAO-Ebene:

\n\n
class UserRepositoryIntegrationTest {\n\n    companion object {\n        private val postgres = PostgreSQLContainer<Nothing>("postgres:15").apply {\n            withDatabaseName("testdb")\n            withUsername("test")\n            withPassword("test")\n            start()\n                

Blogs

Buchempfehlungen