J'ai mis en place un test JUnit (4.12) avec la fonction ExpectedException, et j'aimerais que le test se poursuive après l'exception attendue. Mais je ne vois jamais le log '3', car l'exécution semble s'arrêter après l'exception, événement si catch?
Est-ce réellement possible et comment?
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void testUserAlreadyExists() throws Exception {
log.info("1");
// Create some users
userService.createUser("toto1");
userService.createUser("toto2");
userService.createUser("toto3");
Assert.assertTrue( userService.userExists("toto1") );
Assert.assertTrue( userService.userExists("toto2") );
Assert.assertTrue( userService.userExists("toto3") );
log.info("2");
// Try to create an existing user
exception.expect(AlreadyExistsException.class);
userService.createUser("toto1");
log.info("3");
}
Vous ne pouvez pas faire cela, lorsque l'exception est levée, elle est levée pour de vrai, ExpectedException
règle ou non.
Si vous voulez vraiment ce genre de comportement, vous pouvez revenir au schéma "old school":
try {
userService.createUser("toto1");
Assert.fail("expecting some AlreadyExistsException here")
} catch (AlreadyExistsException e) {
// ignore
}
log.info("3");
Mais je ne me dérangerais pas pour un journal.
Cette solution SO semble faire ce que vous voulez faire: JUnit continue d'affirmer les choses après l'exception attendue
Je pensais moi-même quelque chose de similaire. Pour continuer le test, vous devez intercepter vous-même l'exception dans le test. Cette solution montre une manière élégante de le faire.
Remarque: Si vous créez une règle pour attendre une exception (comme vous l'avez fait), le test retournera avec succès dès que cette exception sera levée. Référence: http://junit.org/javadoc/latest/org/junit/rules/ExpectedException.html
Si vous ne voulez pas ajouter beaucoup de méthodes de test similaires pour quelque chose qui a de nombreuses options pour lever l'exception attendue et que vous voulez vérifier qu'elle se déclenche réellement tous des cas souhaités dans une seule unité -test à la place, je suggère ce schéma (pas assez peut-être) utile:
@Test
public void testThatSomethingExpectedlyFails() {
for (int i = 1; i <= 3; i++) {
try {
switch (i) {
case 1: // smth here throws the exception when configuration #1;
case 2: // smth here throws the exception when configuration #2;
case 3: // smth here throws the exception when configuration #3;
}
} catch (ExceptionThatIsExpected expected) {
continue;
} catch (Exception unexpected) {
/* the test must fail when an unexpected exception is thrown */
fail("The test has failed due to an unexpected exception: " + unexpected.getMessage()); // or just re-throw this exception
}
/* the test must fail when a case completes without the expected exception */
fail("No expected exception occurred at case " + i);
}
}
Celui-ci pourrait également itérer des éléments (et même exécuter des fonctions) d'une liste préparée au préalable au lieu d'un commutateur avec des entiers codés en dur.
Tout d'abord, votre test ne teste rien. Il teste "userExists" et "createUser" dans différentes conditions, comme différents scénarios. Cela s'appelle une AssertionRoulette. Vous n'auriez pas besoin d'un hack pour continuer à enregistrer "3", si vous écrivez des tests, qui échouent pour la bonne raison.
Si les tests échouent pour la bonne raison, vous pouvez voir le scénario de l'échec sans effectuer toutes les tâches de journalisation. Junit-Runner effectue déjà la journalisation pour vous.
@Test
public void testUserExists_UserCreatedUserNotExistent_expectTrue()
{
// Create some users
userService.createUser("toto1");
// Assert That user exists
Assert.assertTrue( userService.userExists("toto1") );
}
@Test
public void testCreateUser_UserAlreadyCreated_expectAlreadyExistsExceptionIsThrown()
{
// Create some users
userService.createUser("toto1");
// Try to create an existing user
exception.expect(AlreadyExistsException.class);
userService.createUser("toto1");
}