web-dev-qa-db-fra.com

Comment continuer le test après JUnit ExpectedException s'il est levé?

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");
}
16
Deathtiny

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.

14
user180100

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

3
Victor Silva

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.

2
Vladyslav Bezuhlyi

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");    
}
1
thepacker