0Pricing
Android Academy · Leçon

Tests unitaires avec JUnit

Écrivez des tests unitaires rapides et fiables avec JUnit 4. Utilisez @Test, @Before, @After et les assertions, testez LiveData avec InstantTaskExecutorRule et les coroutines avec runTest.

Tests unitaires avec JUnit est une leçon Android Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Android Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Android Academy comprend 4 leçons au total.

Pourquoi écrire des tests ?

Les tests ne sont pas un luxe : ils constituent votre filet de sécurité :

  • Détecter les bogues avant les utilisateurs
  • Refactoriser en toute confiance (si les tests réussissent, rien n’est cassé)
  • Documenter le comportement attendu
  • Éviter les régressions lors de l’ajout de fonctionnalités

Un code bien testé est également souvent mieux conçu : s’il est difficile à tester, sa conception est probablement trop fortement couplée.

Types de tests Android

Deux catégories :

  • Tests unitaires (dossier test/) — s’exécutent sur le JVM, sans appareil. Rapides. Testent la logique Kotlin/Java classique.
  • Tests instrumentés (dossier androidTest/) — s’exécutent sur un appareil ou un émulateur. Plus lents. Testent le code propre à Android (base de données Room, interface utilisateur).

Privilégiez les tests unitaires pour la logique métier. Utilisez les tests instrumentés uniquement lorsque vous devez interagir avec les API Android.

Configuration de JUnit 4

JUnit 4 est inclus par défaut dans les projets Android. Ajoutez ces éléments à app/build.gradle :

// app/build.gradle:
dependencies {
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
    testImplementation 'androidx.arch.core:core-testing:2.2.0'  // for LiveData
}

Votre premier test JUnit

Créez une classe dans src/test/java/ et annotez les méthodes de test avec @Test :

import org.junit.Test
import org.junit.Assert.*

class CalculatorTest {

    private val calc = Calculator()

    @Test
    fun `addition returns correct sum`() {
        val result = calc.add(2, 3)
        assertEquals(5, result)
    }

    @Test
    fun `division by zero throws exception`() {
        assertThrows(ArithmeticException::class.java) {
            calc.divide(10, 0)
        }
    }
}

@Before et @After

Utilisez les annotations du cycle de vie pour initialiser et réinitialiser l’état autour de chaque test :

class UserRepositoryTest {

    private lateinit var repo: UserRepository
    private lateinit var fakeDao: FakeUserDao

    @Before
    fun setUp() {
        fakeDao = FakeUserDao()          // fresh instance before each test
        repo = UserRepository(fakeDao)
    }

    @After
    fun tearDown() {
        fakeDao.clear()                  // clean up after each test
    }

    @Test
    fun `getUsers returns all users`() {
        fakeDao.insert(User(1, "Alice"))
        fakeDao.insert(User(2, "Bob"))
        assertEquals(2, repo.getUsers().size)
    }
}

Assertions courantes

JUnit fournit des méthodes d’assertion dans Assert.* :

// Equality:
assertEquals(expected, actual)
assertNotEquals(unexpected, actual)

// Null:
assertNull(value)
assertNotNull(value)

// Boolean:
assertTrue(condition)
assertFalse(condition)

// Same object reference:
assertSame(expected, actual)

// Custom message on failure:
assertEquals("User ID should be 1", 1, user.id)

// Exception:
assertThrows(IllegalArgumentException::class.java) {
    User(id = -1, name = "")
}

Tester un ViewModel

Pour tester LiveData, ajoutez InstantTaskExecutorRule afin que LiveData publie les valeurs de manière synchrone :

class UserViewModelTest {

    @get:Rule
    val instantTaskRule = InstantTaskExecutorRule()

    private val fakeRepo = FakeUserRepository()
    private lateinit var viewModel: UserViewModel

    @Before
    fun setUp() {
        viewModel = UserViewModel(fakeRepo)
    }

    @Test
    fun `users are loaded on init`() {
        fakeRepo.usersToReturn = listOf(User(1, "Alice"), User(2, "Bob"))
        viewModel.loadUsers()

        val result = viewModel.users.value
        assertNotNull(result)
        assertEquals(2, result?.size)
    }
}

Tester les coroutines

Utilisez TestCoroutineDispatcher / StandardTestDispatcher pour contrôler l’exécution des coroutines dans les tests :

class SyncWorkerTest {

    @get:Rule
    val instantTaskRule = InstantTaskExecutorRule()

    private val testDispatcher = StandardTestDispatcher()

    @Before
    fun setUp() {
        Dispatchers.setMain(testDispatcher)
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain()
    }

    @Test
    fun `sync completes successfully`() = runTest {
        val repo = FakeRepository()
        val worker = SyncUseCase(repo, testDispatcher)
        val result = worker.run()
        assertTrue(result.isSuccess)
    }
}

Faux objet ou mock

Deux stratégies pour remplacer les dépendances réelles dans les tests :

  • Faux objet — une implémentation fonctionnelle conçue pour les tests (par exemple une liste en mémoire à la place d’une vraie base de données). Facile à écrire, lisible et sans bibliothèque nécessaire.
  • Mock — un bouchon généré automatiquement qui enregistre les appels et vous permet de vérifier les interactions (Mockito, MockK). Plus puissant, mais potentiellement fragile en cas d’utilisation excessive.

Privilégiez les faux objets dans les cas simples : utilisez les mocks lorsque vous devez vérifier les appels de méthodes.

Écrire un faux objet

Un faux objet implémente la même interface que la classe réelle, mais utilise un stockage en mémoire :

interface UserDao {
    fun getAll(): List<User>
    fun insert(user: User)
}

class FakeUserDao : UserDao {
    private val storage = mutableListOf<User>()

    override fun getAll(): List<User> = storage.toList()
    override fun insert(user: User) { storage.add(user) }

    fun clear() { storage.clear() }
}

Convention de nommage des tests

De bons noms de tests décrivent ce qui est testé et le résultat attendu. Utilisez des noms de fonctions entre apostrophes inverses en Kotlin pour obtenir des descriptions lisibles :

  • `getUsers returns empty list when no users exist`
  • `login throws exception when password is blank`
  • `add returns correct sum for negative numbers`

Schéma : `subject does X when Y`

Vérification rapide

Quel est le rôle de @Before dans une classe de test JUnit ?

Récapitulatif&nbsp;: tests unitaires avec JUnit

Les applications fiables sont des applications testées :

  • Les tests unitaires vont dans src/test/ et s’exécutent sur le JVM : ils sont rapides
  • Annotez-les avec @Test et utilisez assertEquals, assertTrue, assertThrows
  • @Before / @After pour l’initialisation et le nettoyage
  • InstantTaskExecutorRule pour tester LiveData de manière synchrone
  • runTest + StandardTestDispatcher pour tester les coroutines
  • Privilégiez les faux objets aux mocks pour les substitutions simples

Ensuite : les mocks avec Mockito pour vérifier les interactions.

Questions Fréquemment Posées

La leçon « Tests unitaires avec JUnit » est-elle gratuite ?

Oui — le texte complet de « Tests unitaires avec JUnit » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Android Academy, passe à CoddyKit PRO. Le cours Android Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Tests unitaires avec JUnit » ?

Écrivez des tests unitaires rapides et fiables avec JUnit 4. Utilisez @Test, @Before, @After et les assertions, testez LiveData avec InstantTaskExecutorRule et les coroutines avec runTest. Tu pratiques Android Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Android Academy ?

Aucune expérience préalable n'est requise. Android Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Tests unitaires avec JUnit » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Android Academy ?

Oui. Chaque leçon Android Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Tests unitaires avec JUnit
  2. Simulation avec Mockito
  3. Tests d’interface avec Espresso
  4. Débogage et profilage
← Retour à Android Academy