web-dev-qa-db-fra.com

assertAll vs plusieurs assertions dans JUnit5

Y a-t-il une raison de regrouper plusieurs assertions:

public void shouldTellIfPrime(){
    Assertions.assertAll(
            () -> assertTrue(isPrime(2)),
            () -> assertFalse(isPrime(4))
    );
}

au lieu de faire ceci:

public void shouldTellIfPrime(){
    Assertions.assertTrue(isPrime(2));
    Assertions.assertFalse(isPrime(4));
}
24
Wilhelm Olejnik

La chose intéressante à propos de assertAll est qu'elle vérifie toujours toutes les assertions qui lui sont transmises , peu importe le nombre d'échecs. Si tout réussit, tout va bien - si au moins un échoue, vous obtenez un résultat détaillé de tout ce qui s'est mal passé (et c'est vrai d'ailleurs).

Il est préférable de l'utiliser pour affirmer un ensemble de propriétés qui appartiennent ensemble conceptuellement. Quelque chose où votre premier instinct serait, "Je veux affirmer cela comme un".

Exemple

Votre exemple spécifique n'est pas un cas d'utilisation optimal pour assertAll car la vérification de isPrime avec un premier et un non premier est indépendante l'une de l'autre - à tel point que je recommanderais d'écrire deux méthodes de test pour cette.

Mais supposons que vous ayez une classe simple comme une adresse avec les champs city, street, number et que vous souhaitez affirmer que ce sont ce que vous attendez d'eux:

Address address = unitUnderTest.methodUnderTest();
assertEquals("Redwood Shores", address.getCity());
assertEquals("Oracle Parkway", address.getStreet());
assertEquals("500", address.getNumber());

Maintenant, dès que la première assertion échoue, vous ne verrez jamais les résultats de la seconde, ce qui peut être assez ennuyeux. Il y a plusieurs façons de contourner cela et le assertAll de JUnit Jupiter en fait partie:

Address address = unitUnderTest.methodUnderTest();
assertAll("Should return address of Oracle's headquarter",
    () -> assertEquals("Redwood Shores", address.getCity()),
    () -> assertEquals("Oracle Parkway", address.getStreet()),
    () -> assertEquals("500", address.getNumber())
);

Si la méthode testée renvoie la mauvaise adresse, voici l'erreur que vous obtenez:

org.opentest4j.MultipleFailuresError:
    Should return address of Oracle's headquarter (3 failures)
    expected: <Redwood Shores> but was: <Walldorf>
    expected: <Oracle Parkway> but was: <Dietmar-Hopp-Allee>
    expected: <500> but was: <16>
32
Nicolai

Selon la documentation ici

Affirme que tous les exécutables fournis ne lèvent pas une AssertionError.

Si un exécutable fourni renvoie une AssertionError, tous les exécutables restants seront toujours exécutés et tous les échecs seront agrégés et signalés dans une MultipleFailuresError. Cependant, si un exécutable lève une exception qui n'est pas une AssertionError, l'exécution s'arrête immédiatement et l'exception est renvoyée telle quelle mais masquée comme une exception non vérifiée.

Donc, la principale différence est que assertAll permettra à tous les asserts de s'exécuter sans interrompre le flux tandis que les autres comme assertTrue et le lot arrêtera le test avec la AssertionError

Ainsi, dans votre premier exemple, les deux assertions s'exécuteront indépendamment de la réussite à l'échec, tandis que dans le deuxième exemple, le test s'arrêtera si la première assertion échoue.

Y a-t-il une raison de regrouper plusieurs assertions

Si vous voulez que toutes les assertions soient exercées dans le test unitaire.

2
Nkosi