Einführung in das Testen in Kotlin: von Modulen bis zur Benutzererfahrung
Kotlin ist eine moderne Sprache, die aktiv für die Entwicklung von Serveranwendungen (Ktor, Spring Boot), Android-Apps und plattformübergreifenden Projekten verwendet wird. Allerdings ist Code-Qualität ohne fundiertes Testen unmöglich. In diesem Artikel betrachten wir drei Schlüsselebenen: Unit (Modultests), Integration (Integrationstests) und E2E (End-to-End-Tests). Sie erfahren, welche Werkzeuge Sie verwenden, wie Sie Tests in Kotlin schreiben und wie Sie eine zuverlässige Teststrategie für Ihre Anwendung aufbauen.
1. Unit-Testing in Kotlin: Grundlage der Stabilität
Unit-Tests überprüfen einzelne Funktionen, Klassen oder Methoden isoliert von externen Abhängigkeiten. In Kotlin werden dafür hauptsächlich JUnit 5 und MockK verwendet.
Werkzeuge und Einrichtung
Fügen Sie die Abhängigkeiten in build.gradle.kts hinzu:
dependencies { testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") testImplementation("io.mockk:mockk:1.13.8")}Beispiel eines Unit-Tests mit MockK
Angenommen, wir haben einen Service, der von einem Repository abhängt:
class UserService(private val repo: UserRepository) { fun getUserName(id: Int): String { val user = repo.findById(id) return user?.name ?: "Unknown" }}Test mit MockK:
import io.mockk.everyimport io.mockk.mockkimport org.junit.jupiter.api.Assertions.assertEqualsimport org.junit.jupiter.api.Test
class UserServiceTest { @Test fun `getUserName returns name when user exists`() { val mockRepo = mockk<UserRepository>() every { mockRepo.findById(1) } returns User(1, "Alice") val service = UserService(mockRepo) assertEquals("Alice", service.getUserName(1)) }}Bewährte Praktiken für Unit-Tests
- Ein Test – eine Überprüfung (verwenden Sie
assertmit Bedacht). - Isolieren Sie Abhängigkeiten: Verwenden Sie Mocks (MockK) oder Stubs.
- Benennen Sie Tests verständlich:
shouldReturnX_whenY. - Testen Sie Grenzfälle: null, leere Listen, Ausnahmen.
2. Integration-Testing: Überprüfung der Komponentenverknüpfung
Integrationstests überprüfen, wie reale Komponenten zusammenarbeiten: Datenbank, API, Dateisystem. In Kotlin eignen sich dafür Testcontainers und Ktor Client (wenn Sie einen Server schreiben).
Beispiel: Testen eines Repositorys mit PostgreSQL
Binden Sie Testcontainers und exposed (Bibliothek für die Datenbankarbeit) ein:
dependencies { testImplementation("org.testcontainers:postgresql:1.19.3") implementation("org.jetbrains.exposed:exposed:0.44.1")}Test für UserRepository:
import org.junit.jupiter.api.*import org.testcontainers.containers.PostgreSQLContainerimport org.testcontainers.junit.jupiter.Containerimport org.testcontainers.junit.jupiter.Testcontainersimport org.jetbrains.exposed.sql.*
@Testcontainersclass UserRepositoryIntegrationTest {
@Container val postgres = PostgreSQLContainer<Nothing>("postgres:15").apply { withDatabaseName("testdb") withUsername("test") withPassword("test") }
private lateinit var repo: UserRepository
@BeforeEach fun setUp() { Database.connect(postgres.jdbcUrl, driver = "org.postgresql.Driver", user = postgres.username, password = postgres.password) transaction { SchemaUtils.create(Users) } repo = UserRepository() }
@Test fun `save and find user by id`() { val user = User(1, "Bob") repo.save(user) val found = repo.findById(1) assertEquals("Bob", found?.name) }
@AfterEa