Tests en Kotlin : unitaires, d'intégration, E2E de A à Z

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Tests en Kotlin : unitaires, d'intégration, E2E de A à Z

\n\n

Le développement moderne en Kotlin nécessite une approche systématique des tests. Que vous écriviez un backend avec Ktor ou une application mobile Android, une couverture de code de qualité par des tests est la clé de la stabilité et de la prévisibilité du projet. Dans cet article, nous aborderons trois niveaux de tests : les tests unitaires, les tests d'intégration et les tests de bout en bout (E2E). Vous découvrirez quels outils utiliser, comment écrire des tests efficaces en Kotlin et éviter les erreurs courantes.

\n\n

1. Tests unitaires en Kotlin : les bases fondamentales

\n\n

Les tests unitaires vérifient le fonctionnement de fonctions, classes ou méthodes individuelles isolées des dépendances externes. En Kotlin, on utilise le plus souvent le framework JUnit 5 combiné à la bibliothèque de mocks MockK.

\n\n

Configuration du projet

\n\n

Ajoutez les dépendances dans build.gradle.kts :

\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

Exemple de test unitaire

\n\n

Supposons que nous ayons un service simple pour calculer une remise :

\n\n
class DiscountService {\n    fun applyDiscount(price: Double, discountPercent: Int): Double {\n        require(discountPercent in 0..100) { "Le pourcentage de remise doit être compris entre 0 et 100" }\n        return price * (100 - discountPercent) / 100\n    }\n}\n
\n\n

Test pour ce service :

\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 calcule correctement une remise de 50 pourcents`() {\n        val result = service.applyDiscount(1000.0, 50)\n        assertEquals(500.0, result, 0.001)\n    }\n\n    @Test\n    fun `applyDiscount lève une exception pour un pourcentage invalide`() {\n        assertThrows<IllegalArgumentException> {\n            service.applyDiscount(100.0, 150)\n        }\n    }\n}\n
\n\n

Conseil : Utilisez assertThrows pour vérifier les exceptions et nommez les tests avec des chaînes claires — cela améliore la lisibilité des rapports.

\n\n

Mocking avec MockK

\n\n

Lorsque votre classe dépend d'autres composants (par exemple, un repository ou une API), utilisez des mocks :

\n\n
class OrderService(private val paymentGateway: PaymentGateway) {\n    fun processOrder(amount: Double): String {\n        if (paymentGateway.charge(amount)) {\n            return "Paiement réussi"\n        }\n        return "Erreur de paiement"\n    }\n}\n\n// Test\n@Test\nfun `processOrder retourne un succès lors d'un paiement réussi`() {\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("Paiement réussi", result)\n    verify { mockGateway.charge(500.0) }\n}\n
\n\n

2. Tests d'intégration : vérification de l'interaction des composants

\n\n

Les tests d'intégration vérifient comment différentes parties du système fonctionnent ensemble : base de données, API externes, système de fichiers. Pour Kotlin, Testcontainers est parfait — une bibliothèque pour lancer des conteneurs Docker pendant les tests.

\n\n

Exemple avec une base de données PostgreSQL

\n\n

Ajoutez les dépendances :

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

Écrivons un test pour la couche DAO :

\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

Book Recommendations