W3docs

Assertions JUnit en Java

Vérifiez le comportement dans JUnit 5 avec assertEquals, assertTrue, assertThrows, assertAll et bien d'autres méthodes.

Une assertion est le moment où un test cesse de décrire et commence à vérifier — elle énonce ce que le code doit produire et fait échouer le test si la réalité ne correspond pas. JUnit 5 (l'API Jupiter) regroupe toutes les assertions en tant que méthodes static sur une seule classe, org.junit.jupiter.api.Assertions. Maîtrisez cette poignée de méthodes et vous pourrez exprimer presque n'importe quelle attente : égalité, vérité, nullité, identité, exceptions levées, délais d'attente et vérifications groupées. Ce chapitre passe en revue celles que vous utilisez au quotidien.

Si vous débutez avec ce framework, lisez d'abord l'introduction à JUnit, puis les annotations JUnit pour comprendre d'où viennent les méthodes @Test. Les assertions se trouvent à l'intérieur de ces méthodes.

Le modèle mental : une assertion échouée fait échouer le test

Une méthode de test JUnit s'exécute de haut en bas. Chaque assertion qui est vérifiée est silencieuse ; la première qui n'est pas vérifiée lève une AssertionFailedError, que JUnit intercepte et enregistre comme un échec — la méthode s'arrête à ce stade. Les assertions sont donc les points de sortie du test. L'ordre conventionnel des arguments est attendu en premier, réel en second, et chaque méthode accepte un message final facultatif utilisé uniquement lorsque la vérification échoue :

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

class CalculatorTest {
  @Test
  void addsTwoNumbers() {
    int result = 2 + 3;
    assertEquals(5, result, "2 + 3 should equal 5");
  }
}

Vous importez les méthodes de manière statique (import static ... Assertions.*) afin que le corps du test se lise comme de l'anglais courant — assertEquals(...), et non Assertions.assertEquals(...).

Égalité, vérité et nullité

Ces quatre catégories couvrent la grande majorité des assertions réelles :

MéthodeRéussit quand
assertEquals(expected, actual)expected.equals(actual) est vrai
assertNotEquals(unexpected, actual)les deux ne sont pas égaux
assertTrue(condition) / assertFalse(condition)le booléen est true / false
assertNull(obj) / assertNotNull(obj)la référence est / n'est pas null
assertSame(expected, actual)les deux désignent le même objet (==)
assertArrayEquals(expected, actual)les tableaux sont égaux élément par élément
assertEquals("HELLO", "hello".toUpperCase());
assertTrue(List.of(1, 2, 3).contains(2), "list should contain 2");
assertNull(map.get("missing"));
assertNotSame(new String("a"), new String("a")); // distinct objects
assertArrayEquals(new int[]{1, 2, 3}, computeRange(3));

assertEquals utilise .equals(), donc deux objets String différents ayant les mêmes caractères passent ; assertSame utilise ==, donc ils échouent. Recourez à assertSame uniquement lorsque c'est l'identité de l'objet que vous souhaitez tester.

Tester les exceptions avec assertThrows

Un test affirme parfois que du code échoue — qu'une entrée invalide lève une exception. assertThrows prend le type d'exception et un lambda ; il réussit uniquement si l'exécution du lambda lève ce type (ou un sous-type), et il retourne l'exception interceptée afin que vous puissiez inspecter son message :

@Test
void rejectsNullName() {
  IllegalArgumentException ex = assertThrows(
      IllegalArgumentException.class,
      () -> greet(null));
  assertEquals("name must not be null", ex.getMessage());
}

Son image miroir est assertDoesNotThrow, qui échoue si le lambda lève quoi que ce soit — utile pour affirmer qu'un chemin auparavant bogué s'exécute maintenant proprement. (Pour les règles régissant les exceptions que votre code lève, consultez Java exceptions.)

Regroupement avec assertAll

Par défaut, la première assertion échouée termine la méthode, masquant ainsi les problèmes suivants. assertAll exécute chaque assertion contenue même lorsque certaines échouent, puis rapporte tous les échecs ensemble — idéal pour vérifier plusieurs propriétés d'un même objet :

@Test
void buildsCompleteUser() {
  User u = User.of("[email protected]");
  assertAll("user",
      () -> assertEquals("[email protected]", u.email()),
      () -> assertTrue(u.isActive()),
      () -> assertNotNull(u.createdAt()));
}

Si l'e-mail et le drapeau actif sont tous deux incorrects, une seule exécution vous l'indique — au lieu de corriger l'un, de relancer et de découvrir le suivant.

Un exemple concret : une exécution de test auto-vérifiée, sans framework

L'exécuteur de code n'a pas JUnit dans son classpath, donc ce programme implémente la même idée en Java pur : de petits assistants assertEquals, assertTrue, assertThrows et assertAll qui se comportent comme ceux de Jupiter — silencieux en cas de succès, expressifs en cas d'échec — pilotant quelques méthodes sous test et affichant un bilan de type runner à la fin. L'API que vous utiliseriez réellement se trouve dans les blocs statiques ci-dessus ; celui-ci montre ce que ces méthodes font.

java— editable, runs on the server

Ce qu'il faut retenir de l'exécution :

  • Les vérifications réussies ne produisent aucune ligne d'échec — seuls add(2,3) verified == 5 et tag conditions verified s'affichent, reflétant la règle de JUnit selon laquelle une assertion satisfaite est silencieuse et seuls les échecs s'expriment.
  • assertThrows a affiché caught expected IllegalArgumentException: name must not be null, illustrant le schéma : le lambda doit lever une exception, le type doit correspondre, et le message de l'exception interceptée vous appartient pour une assertion ultérieure.
  • assertAll ran 3 checks, 0 failed confirme le comportement de regroupement — les trois lambdas ont été exécutés et comptabilisés ensemble, ce qui est précisément la raison pour laquelle assertAll expose chaque problème en un seul passage au lieu de s'arrêter au premier.
  • Le SUMMARY -> passed: 7, failed: 0 final comptabilise sept assertions individuelles dans l'ensemble du programme (une égalité, deux booléens, un throws et trois dans assertAll), le même bilan qu'un vrai runner rapporte — chaque appel à assertX est une vérification.
  • Rien ici n'a importé de framework de test, pourtant la structure est identique à Jupiter : des assistants silencieux en cas de succès et explicites en cas d'échec. Remplacer ceux-ci par org.junit.jupiter.api.Assertions.* changerait les imports, pas la façon de raisonner sur chaque vérification.
Avertissement

L'ordre des arguments perturbe presque tout le monde au début : c'est assertEquals(expected, actual), jamais l'inverse. Intervertissez-les et le test fonctionnera quand même, mais un message d'échec sera à l'envers — il affirme que votre valeur correcte est fausse et que la valeur boguée est juste. Mettez toujours la valeur littérale ou connue-bonne en premier.

Que faire ensuite

Les assertions ne sont qu'une pièce d'une méthode de test. Pour les utiliser efficacement :

  • Regroupez la configuration et le démontage autour d'elles avec les rappels du cycle de vie JUnit (@BeforeEach, @AfterEach).
  • Exécutez les mêmes assertions sur de nombreuses entrées sans copier-coller en utilisant les tests paramétrés.
  • Revisitez la référence des annotations pour @Test, @DisplayName et @Disabled.

Pratique

Pratique
Dans JUnit 5, qu'est-ce qu'assertAll vous apporte qu'une séquence d'assertions séparées ne donne pas ?
Dans JUnit 5, qu'est-ce qu'assertAll vous apporte qu'une séquence d'assertions séparées ne donne pas ?
Was this page helpful?