Testen in Kotlin: Unit-, Integrations- und E2E-Tests – das vollständige Handbuch

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

Einführung in das Testen in Kotlin: von Unit-Tests bis End-to-End

Testen ist ein wesentlicher Bestandteil der Entwicklung zuverlässiger Software. Im Kotlin-Ökosystem, das aktiv für die Android-Entwicklung, Backend mit Ktor und plattformübergreifende Projekte genutzt wird, gibt es leistungsstarke Werkzeuge für alle Testebenen. In diesem Artikel betrachten wir drei Schlüsselebenen: Unit-Tests, Integrationstests und End-to-End (E2E) Tests. Sie erfahren, wie sie sich unterscheiden, wann sie anzuwenden sind und wie man effektive Tests in Kotlin mit Codebeispielen schreibt.



Unit-Testing in Kotlin: Grundlage der Zuverlässigkeit

Unit-Tests überprüfen die Arbeit einzelner Komponenten (Funktionen, Klassen) in Isolation. In Kotlin ist der De-facto-Standard das Framework JUnit 5 in Verbindung mit der Mock-Bibliothek MockK.



Beispiel eines Unit-Tests mit JUnit 5 und MockK

Betrachten wir einen einfachen Service zur Berechnung eines Rabatts:

class DiscountService(private val userRepository: UserRepository) {    fun calculateDiscount(userId: String, amount: Double): Double {        val user = userRepository.findById(userId) ?: return amount        return if (user.isPremium) amount * 0.9 else amount    }}

Test für diesen Service:

import io.mockk.everyimport io.mockk.mockkimport org.junit.jupiter.api.Testimport kotlin.test.assertEquals

class DiscountServiceTest {

@Test fun `should apply 10% discount for premium user`() { // Arrange val userRepo = mockk<UserRepository>() every { userRepo.findById("123") } returns User("123", isPremium = true) val service = DiscountService(userRepo)

// Act val result = service.calculateDiscount("123", 100.0)

// Assert assertEquals(90.0, result) }

@Test fun `should not apply discount for regular user`() { val userRepo = mockk<UserRepository>() every { userRepo.findById("456") } returns User("456", isPremium = false) val service = DiscountService(userRepo)

val result = service.calculateDiscount("456", 100.0)

assertEquals(100.0, result) }}

Wichtige Punkte:

  • Verwenden Sie mockk{} zum Erstellen von Mocks.
  • Der Block every { ... } returns ... definiert das Verhalten des Mocks.
  • Die Struktur Arrange-Act-Assert macht Tests lesbar.
  • Unit-Tests sollten schnell ausgeführt werden und nicht von externen Ressourcen abhängen.


Integrationstesting: Überprüfung der Komponenteninteraktion

Integrationstests überprüfen, wie mehrere Module zusammenarbeiten – zum Beispiel ein Service mit einer echten Datenbank oder einer externen API. Für Kotlin sind Testcontainers (für Docker-Container) und Spring Boot Test (für Backend) beliebt.



Beispiel eines Integrationstests mit Testcontainers und Ktor

Angenommen, wir haben eine Ktor-Anwendung mit PostgreSQL:

class UserRepository(private val database: Database) {    suspend fun findById(id: String): User? {        return database.query("SELECT * FROM users WHERE id = ?", id).singleOrNull { row ->            User(row.string("id"), row.boolean("is_premium"))        }    }}

Integrationstest mit Testcontainers:

import io.kotest.core.spec.style.StringSpecimport io.kotest.matchers.shouldBeimport org.testcontainers.containers.PostgreSQLContainerimport org.testcontainers.junit.jupiter.Containerimport org.testcontainers.junit.jupiter.Testcontainers

@Testcontainersclass UserRepositoryIntegrationTest : StringSpec({

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

"should

Blogs

Buchempfehlungen