web-dev-qa-db-fra.com

Mockito Comment se moquer et affirmer une exception levée?

J'utilise mockito dans un test junit. Comment créer une exception et ensuite affirmer qu'elle existe (pseudo-code générique)

96
stackoverflow

BDD Style Solution

Mockito n'est pas la meilleure solution pour gérer les exceptions, utilisez Mockito avec Catch-Exception 

Mockito + Catch-Exception + AssertJ

given(otherServiceMock.bar()).willThrow(new MyException());

when(myService).foo();

then(caughtException()).isInstanceOf(MyException.class);

Exemple de code

Les dépendances

  • eu.codearte.catch-exception: catch-exception: 1.3.3
  • org.assertj: assertj-core: 1.7.0

Désavantage

  • Seul Mockito jusqu'à 1.10.8 est pris en charge
62
MariuszS

Pour répondre à votre deuxième question en premier. Si vous utilisez JUnit 4, vous pouvez annoter votre test avec 

@Test(expected=MyException.class)

pour affirmer qu'une exception s'est produite. Et pour "se moquer" d'une exception avec mockito, utilisez

when(myMock.doSomething()).thenThrow(new MyException());
163
NilsH

Si vous souhaitez également tester le message d'exception, vous pouvez utiliser ExpectedException de JUnit avec Mockito:

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void testExceptionMessage() throws Exception {
    expectedException.expect(AnyException.class);
    expectedException.expectMessage("The expected message");

    given(foo.bar()).willThrow(new AnyException("The expected message"));
}
19
Daniel Treiber

Faites que l'exception se produise comme ceci:

when(obj.someMethod()).thenThrow(new AnException());

Vérifiez que cela est arrivé soit en affirmant que votre test lève une telle exception:

@Test(expected = AnException.class)

Ou par vérification fictive normale:

verify(obj).someMethod();

Cette dernière option est requise si votre test est conçu pour prouver que le code intermédiaire gère l’exception (c’est-à-dire que l’exception ne sera pas levée par votre méthode de test).

15
Duncan Jones

Si vous utilisez JUnit 4 et Mockito 1.10.x Annotez votre méthode de test avec:

@Test(expected = AnyException.class)

et pour lancer votre exception souhaitée, utilisez:

Mockito.doThrow(new AnyException()).when(obj).callAnyMethod();
12
Prashant Kumar

Réponse mise à jour pour le 19/06/2015 (si vous utilisez Java 8)

Il suffit d'utiliser assertj

Utilisation de assertj-core-3.0.0 + Java 8 Lambdas 

@Test
public void shouldThrowIllegalArgumentExceptionWhenPassingBadArg() {
assertThatThrownBy(() -> myService.sumTingWong("badArg"))
                                  .isInstanceOf(IllegalArgumentException.class);
}

Référence: http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-Java-8.html

10
Selwyn

Utilisez Mockito's doThrow , puis saisissez l'exception souhaitée pour affirmer qu'elle a été émise plus tard.

@Test
public void fooShouldThrowMyException() {
    // given
    val myClass = new MyClass();
    val arg = mock(MyArgument.class);
    doThrow(MyException.class).when(arg).argMethod(any());
    Exception exception = null;

    // when
    try {
        myClass.foo(arg);
    } catch (MyException t) {
        exception = t;
    }

    // then
    assertNotNull(exception);
}
1
Rodrigo Martins

Sans lien avec mockito, on peut attraper l'exception et en affirmer les propriétés. Pour vérifier que l'exception s'est bien produite, associez une condition fausse au bloc try après l'instruction qui lève l'exception.

0
eel ghEEz

Ou si votre exception est levée par le constructeur d'une classe: 

@Rule
public ExpectedException exception = ExpectedException.none();

@Test
public void myTest() {    

    exception.expect(MyException.class);
    CustomClass myClass= mock(CustomClass.class);
    doThrow(new MyException("constructor failed")).when(myClass);  

}
0
JediCate