web-dev-qa-db-fra.com

Test de plusieurs exceptions avec les annotations JUnit 4

Est-il possible de tester plusieurs exceptions dans un seul test unitaire JUnit? Je sais que, pour une seule exception, on peut utiliser, par exemple

    @Test(expected=IllegalStateException.class)

Maintenant, si je veux tester une autre exception (par exemple, NullPointerException), cela peut-il être fait dans la même annotation, une annotation différente ou dois-je écrire complètement un autre test unitaire?

24
phantom-99w

Vous voulez vraiment que le test fasse un chose, et pour tester cela. Si vous ne savez pas quelle exception va être levée, cela ne me semble pas être un bon test.

par exemple. (en pseudo-code)

try {
   badOperation();
   /// looks like we succeeded. Not good! Fail the test
   fail();
}
catch (ExpectedException e) {
   // that's fine
}
catch (UnexpectedException e) {
   // that's NOT fine. Fail the test
}

par conséquent, si vous souhaitez vérifier que votre méthode génère deux exceptions différentes (pour 2 jeux d'entrées), vous aurez besoin de 2 tests.

22
Brian Agnew

Ce n'est pas possible avec l'annotation.

Avec JUnit 4.7, vous pouvez utiliser la nouvelle règle ExpectedException

public static class HasExpectedException {
    @Interceptor
    public ExpectedException thrown= new ExpectedException();

    @Test
    public void throwsNothing() {
    }

    @Test
    public void throwsNullPointerException() {
         thrown.expect(NullPointerException.class);
         throw new NullPointerException();
    }

    @Test
    public void throwsNullPointerExceptionWithMessage() {
        thrown.expect(NullPointerException.class);
        thrown.expectMessage("happened?");
        throw new NullPointerException("What happened?");
    }
}

Plus voir


Si la mise à jour vers JUnit 4.7 ne vous est pas possible, vous devez écrire un test à l'unité nue du formulaire.

public test() {
    try {
        methodCall(); // should throw Exception
        fail();
    }
    catch (Exception ex) {
        assert((ex instanceof A) || (ex instanceof B) || ...etc...);
        ...
    }

}

12
akuhn

Utilisez catch-exception :

// test 
public void testDo() {

   // obj.do(1) must throw either A or B
   catchException(obj).do(1);
   assert caughtException() instanceof A
       || caughtException() instanceof B;

   // obj.do(2) must throw A but not SubclassOfA
   catchException(obj).do(2);
   assert caughtException() instanceof A
       && !(caughtException() instanceof SubclassOfA);

}
3
rwitzel

Bien que cela ne soit pas possible avec JUnit 4, il est possible si vous passez à TestNG, ce qui vous permet d’écrire 

@Test(expectedExceptions = {IllegalArgumentException.class, NullPointerException.class})
2
Breandán Dalton

Gardez les tests aussi simples et courts que possible. Le but de JUnit-Test est de tester une seule fonctionnalité ou un seul moyen d'échec.

En effet, pour plus de sécurité, vous devez créer au moins un test pour chaque moyen d'exécution possible.

Normalement, cela n’est pas toujours possible, car si vous avez une méthode qui analyse une chaîne, il ya tellement de combinaisons de chaînes possibles que vous ne pouvez pas tout couvrir.

Soyez concis et simple.

Vous pouvez avoir facilement 30 à 40 méthodes de test pour une seule méthode… est-ce vraiment important?

Cordialement

0
Atmocreations

Comment vous attendez-vous à ce que les "attendus" fonctionnent? Une méthode ne peut lancer qu'une seule exception.

Vous devrez écrire un test unitaire différent pour chaque méthode d'échec de la méthode. Donc, si la méthode jette légitimement deux exceptions, vous devez configurer deux tests pour forcer la méthode de levée de chaque exception.

0
@Test(expected=Exception.class)

Cela jettera toutes les exceptions possibles.

0
Raj