Assertions dans JUnit 4 et JUnit 5

Assertions dans JUnit 4 et JUnit 5

1. introduction

Dans cet article, nous allons explorer en détail les assertions disponibles dans JUnit.

Suite aux articlesmigrating from JUnit 4 to JUnit 5 etA Guide to JUnit 5, nous allons maintenant entrer dans les détails des différentes assertions disponibles dans JUnit 4 et JUnit 5.

Nous soulignerons également les améliorations apportées aux assertions avec JUnit 5.

2. Assertions

Assertions are utility methods to support asserting conditions in tests; ces méthodes sont accessibles via la classeAssert, dans JUnit 4, et celleAssertions, dans JUnit 5.

Afin d'augmenter la lisibilité du test et des assertions elles-mêmes, il est toujours recommandé deimport statiquement la classe respective. De cette manière, nous pouvons nous référer directement à la méthode d'assertion elle-même sans la classe de représentation en tant que préfixe.

Commençons par explorer les assertions disponibles avec JUnit 4.

3. Assertions dans JUnit 4

Dans cette version de la bibliothèque, les assertions sont disponibles pour tous les types primitifs,Objects, etarrays (soit des primitives soitObjects).

L'ordre des paramètres, dans l'assertion, est la valeur attendue suivie de la valeur réelle; facultativement, le premier paramètre peut être un messageString qui représente la sortie de message de la condition évaluée.

Il n’y en a qu’une légèrement différente dans la définition des assertionsassertThat, mais nous en parlerons plus tard.

Commençons par celui deassertEquals.

3.1. assertEquals

L'assertionassertEquals vérifie que les valeurs attendues et réelles sont égales:

@Test
public void whenAssertingEquality_thenEqual() {
    String expected = "example";
    String actual = "example";

    assertEquals(expected, actual);
}

Il est également possible de spécifier un message à afficher lorsque l’assertion échoue:

assertEquals("failure - strings are not equal", expected, actual);

3.2. assertArrayEquals

Si nous voulons affirmer que deux tableaux sont égaux, nous pouvons utiliser lesassertArrayEquals:

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = {'J','u','n','i','t'};
    char[] actual = "Junit".toCharArray();

    assertArrayEquals(expected, actual);
}

Si les deux tableaux sontnull, l'assertion les considérera égaux:

@Test
public void givenNullArrays_whenAssertingArraysEquality_thenEqual() {
    int[] expected = null;
    int[] actual = null;

    assertArrayEquals(expected, actual);
}

3.3. assertNotNull etassertNull

Lorsque nous voulons tester si un objet estnull, nous pouvons utiliser l'assertionassertNull:

@Test
public void whenAssertingNull_thenTrue() {
    Object car = null;

    assertNull("The car should be null", car);
}

A l'inverse, si nous voulons affirmer qu'un objet ne doit pas être nul, nous pouvons utiliser lesassertNotNull assertion.

3.4. assertNotSame etassertSame

AvecassertNotSame, il est possible de vérifier si deux variables ne font pas référence au même objet:

@Test
public void whenAssertingNotSameObject_thenDifferent() {
    Object cat = new Object();
    Object dog = new Object();

    assertNotSame(cat, dog);
}

Sinon, lorsque nous voulons vérifier que deux variables font référence au même objet, nous pouvons utiliser l'assertionassertSame.

3.5. assertTrue etassertFalse

Dans le cas où nous voulons vérifier qu'une certaine condition esttrue oufalse, nous pouvons respectivement utiliser l'assertionassertTrue ou celleassertFalse:

@Test
public void whenAssertingConditions_thenVerified() {
    assertTrue("5 is greater then 4", 5 > 4);
    assertFalse("5 is not greater then 6", 5 > 6);
}

3.6. fail

L'assertionfail échoue à un test lançant unAssertionFailedError. Il peut être utilisé pour vérifier qu’une exception réelle est générée ou lorsqu’un test échoue lors de son développement.

Voyons comment nous pouvons l'utiliser dans le premier scénario:

@Test
public void whenCheckingExceptionMessage_thenEqual() {
    try {
        methodThatShouldThrowException();
        fail("Exception not thrown");
    } catch (UnsupportedOperationException e) {
        assertEquals("Operation Not Supported", e.getMessage());
    }
}

3.7. assertThat

L'assertionassertThat est la seule dans JUnit 4 qui a un ordre inverse des paramètres par rapport aux autres assertions.

Dans ce cas, l'assertion a un message d'échec facultatif, la valeur réelle et un objetMatcher.

Voyons comment nous pouvons utiliser cette assertion pour vérifier si un tableau contient des valeurs particulières:

@Test
public void testAssertThatHasItems() {
    assertThat(
      Arrays.asList("Java", "Kotlin", "Scala"),
      hasItems("Java", "Kotlin"));
}

Des informations supplémentaires, sur l'utilisation puissante de l'assertionassertThat avec l'objetMatcher, sont disponibles àTesting with Hamcrest.

4. Assertions JUnit 5

JUnit 5 a conservé de nombreuses méthodes d'assertion de JUnit 4 tout en en ajoutant quelques-unes qui exploitent le support de Java 8.

Également dans cette version de la bibliothèque, les assertions sont disponibles pour tous les types primitifs,Objects, et tableaux (soit des primitives, soit des objets).

L'ordre des paramètres des assertions a changé, déplaçant le paramètre de message de sortie comme dernier paramètre. Grâce au support de Java 8, le message de sortie peut être unSupplier, permettant une évaluation paresseuse de celui-ci.

Commençons par examiner les assertions disponibles également dans JUnit 4.

4.1. assertArrayEquals

L'assertionassertArrayEquals vérifie que les tableaux attendus et réels sont égaux:

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = { 'J', 'u', 'p', 'i', 't', 'e', 'r' };
    char[] actual = "Jupiter".toCharArray();

    assertArrayEquals(expected, actual, "Arrays should be equal");
}

Si les tableaux ne sont pas égaux, le message «Arrays should be equal» sera affiché en sortie.

4.2. assertEquals

Dans le cas où nous voulons affirmer que deuxfloats sont égaux, nous pouvons utiliser l'assertion simpleassertEquals:

@Test
public void whenAssertingEquality_thenEqual() {
    float square = 2 * 2;
    float rectangle = 2 * 2;

    assertEquals(square, rectangle);
}

Cependant, si nous voulons affirmer que la valeur réelle diffère d'un delta prédéfini de la valeur attendue, nous pouvons toujours utiliser lesassertEquals mais nous devons passer la valeur delta comme troisième paramètre:

@Test
public void whenAssertingEqualityWithDelta_thenEqual() {
    float square = 2 * 2;
    float rectangle = 3 * 2;
    float delta = 2;

    assertEquals(square, rectangle, delta);
}

4.3. assertTrue etassertFalse

Avec l'assertionassertTrue, il est possible de vérifier que les conditions fournies sonttrue:

@Test
public void whenAssertingConditions_thenVerified() {
    assertTrue(5 > 4, "5 is greater the 4");
    assertTrue(null == null, "null is equal to null");
}

Grâce au support de l'expression lambda, il est possible de fournir unBooleanSupplier à l'assertion au lieu d'une conditionboolean.

Voyons comment nous pouvons affirmer l'exactitude d'unBooleanSupplier en utilisant l'assertionassertFalse:

@Test
public void givenBooleanSupplier_whenAssertingCondition_thenVerified() {
    BooleanSupplier condition = () -> 5 > 6;

    assertFalse(condition, "5 is not greater then 6");
}

4.4. assertNull etassertNotNull

Lorsque nous voulons affirmer qu'un objet n'est pasnull, nous pouvons utiliser l'assertionassertNotNull:

@Test
public void whenAssertingNotNull_thenTrue() {
    Object dog = new Object();

    assertNotNull(dog, () -> "The dog should not be null");
}

Dans le cas contraire, nous pouvons utiliser l'assertionassertNull pour vérifier si le réel estnull:

@Test
public void whenAssertingNull_thenTrue() {
    Object cat = null;

    assertNull(cat, () -> "The cat should be null");
}

Dans les deux cas, le message d'échec sera récupéré de manière paresseuse puisqu'il s'agit d'unSupplier.

4.5. assertSame etassertNotSame

Lorsque nous voulons affirmer que l'attendu et le réel se réfèrent aux mêmesObject, nous devons utiliser l'assertionassertSame:

@Test
public void whenAssertingSameObject_thenSuccessfull() {
    String language = "Java";
    Optional optional = Optional.of(language);

    assertSame(language, optional.get());
}

Dans le cas contraire, nous pouvons utiliser celui deassertNotSame.

4.6. fail

L'assertionfail échoue à un test avec le message d'échec fourni ainsi que la cause sous-jacente. Cela peut être utile pour marquer un test lorsque son développement n’est pas terminé:

@Test
public void whenFailingATest_thenFailed() {
    // Test not completed
    fail("FAIL - test not completed");
}

4.7. assertAll

L'une des nouvelles assertions introduites dans JUnit 5 estassertAll.

Cette assertion permet la création d'assertions groupées, où toutes les assertions sont exécutées et leurs échecs sont signalés ensemble. En détail, cette assertion accepte un en-tête, qui sera inclus dans la chaîne de message pour lesMultipleFailureError, et unStream deExecutable.

Définissons une assertion groupée:

@Test
public void givenMultipleAssertion_whenAssertingAll_thenOK() {
    assertAll(
      "heading",
      () -> assertEquals(4, 2 * 2, "4 is 2 times 2"),
      () -> assertEquals("java", "JAVA".toLowerCase()),
      () -> assertEquals(null, null, "null is equal to null")
    );
}

L'exécution d'une assertion groupée n'est interrompue que lorsque l'un des exécutables lève une exception sur liste noire (OutOfMemoryError par exemple).

4.8. assertIterableEquals

LeassertIterableEquals affirme que les itérables attendus et réels sont profondément égaux.

Pour être égaux, les deux itérables doivent renvoyer des éléments égaux dans le même ordre et il n'est pas nécessaire que les deux itérables soient du même type pour être égaux.

En tenant compte de cela, voyons comment nous pouvons affirmer que deux listes de types différents (LinkedList etArrayList par exemple) sont égales:

@Test
public void givenTwoLists_whenAssertingIterables_thenEquals() {
    Iterable al = new ArrayList<>(asList("Java", "Junit", "Test"));
    Iterable ll = new LinkedList<>(asList("Java", "Junit", "Test"));

    assertIterableEquals(al, ll);
}

De la même manière que lesassertArrayEquals, si les deux itérables sont nuls, ils sont considérés comme égaux.

4.9. assertLinesMatch

LeassertLinesMatch affirme que la liste attendue deString correspond à la liste réelle.

Cette méthode diffère desassertEquals etassertIterableEquals car, pour chaque paire de lignes attendues et réelles, elle exécute cet algorithme:

  1. vérifie si la ligne attendue est égale à celle réelle. Si oui, cela continue avec la paire suivante

  2. traite la ligne attendue comme une expression régulière et effectue une vérification avec la méthodeString.matches(). Si oui, cela continue avec la paire suivante

  3. vérifie si la ligne attendue est un marqueur d’avance rapide. Si oui, appliquez l'avance rapide et répétez l'algorithme à partir de l'étape 1

Voyons comment nous pouvons utiliser cette assertion pour affirmer que deux listes deString ont des lignes correspondantes:

@Test
public void whenAssertingEqualityListOfStrings_thenEqual() {
    List expected = asList("Java", "\\d+", "JUnit");
    List actual = asList("Java", "11", "JUnit");

    assertLinesMatch(expected, actual);
}

4.10. assertNotEquals

En complément desassertEquals, l'assertionassertNotEquals affirme que les valeurs attendues et réelles ne sont pas égales:

@Test
public void whenAssertingEquality_thenNotEqual() {
    Integer value = 5; // result of an algorithm

    assertNotEquals(0, value, "The result cannot be 0");
}

Si les deux sontnull, l'assertion échoue.

4.11. assertThrows

Afin d'augmenter la simplicité et la lisibilité, la nouvelle assertionassertThrows nous permet un moyen clair et simple d'affirmer si un exécutable lève le type d'exception spécifié.

Voyons comment nous pouvons affirmer une exception levée:

@Test
void whenAssertingException_thenThrown() {
    Throwable exception = assertThrows(
      IllegalArgumentException.class,
      () -> {
          throw new IllegalArgumentException("Exception message");
      }
    );
    assertEquals("Exception message", exception.getMessage());
}

L'assertion échouera si aucune exception n'est levée, ou si une exception d'un type différent est levée.

4.12. assertTimeout et assertTimeoutPréemptivement

Dans le cas où nous voulons affirmer que l'exécution d'unExecutable fourni se termine avant unTimeout donné, nous pouvons utiliser l'assertionassertTimeout:

@Test
public void whenAssertingTimeout_thenNotExceeded() {
    assertTimeout(
      ofSeconds(2),
      () -> {
        // code that requires less then 2 minutes to execute
        Thread.sleep(1000);
      }
    );
}

Cependant, avec l'assertionassertTimeout, l'exécutable fourni sera exécuté dans le même thread du code appelant. Par conséquent, l'exécution du fournisseur ne sera pas interrompue de manière préventive si le délai d'attente est dépassé.

Dans le cas où nous voulons être sûrs que l'exécution de l'exécutable sera abandonnée une fois qu'elle dépasse le délai d'expiration, nous pouvons utiliser l'assertionassertTimeoutPreemptively.

Les deux assertions peuvent accepter, au lieu d'unExecutable, aThrowingSupplier, représentant n'importe quel bloc de code générique qui renvoie un objet et qui peut potentiellement lancer unThrowable.

5. Conclusion

Dans ce tutoriel, nous avons couvert toutes les assertions disponibles dans JUnit 4 et JUnit 5.

Nous avons souligné brièvement les améliorations apportées à JUnit 5, avec l'introduction de nouvelles affirmations et le soutien de lambdas.

Comme toujours, le code source complet de cet article est disponibleover on GitHub.