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


Réponses:


75

Solution de style BDD (mise à jour vers Java 8)

Mockito seul 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

Dépendances


2
Qu'est-ce que "catch-exception"? Vous avez un lien?
Duncan Jones

quoi caughtException?
Saif Masadeh

OK, ça vient decom.googlecode.catchexception.CatchException.caughtException;
Saif Masadeh

212

Pour répondre d'abord à votre deuxième question. 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 "simuler" une exception avec mockito, utilisez

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

2
cette approche est inacceptable pour le cas où vous testez la méthode d'un objet qui a un état. Par exemple, il existe une méthode objet qui lève une exception si vous l'appelez la deuxième fois. Et vous devez tester pour vérifier qu'il lève une exception lors du deuxième appel de méthode, pas du premier. S'il lève MyException lors du premier appel de méthode (dans la phase de préparation), le test doit échouer. Mais avec cette approche, nous ne sommes pas en mesure de vérifier pendant quel appel de méthode l'exception est lancée.
Sneg

Bien que dans ce cas, nous pouvons intercepter l'exception du premier appel de méthode et l'encapsuler dans RuntimeException.
Sneg

29

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

given()D'où est-ce que ça vient?
Mohammad Faisal


Je préfère également utiliser la @Rule, car de cette façon, je peux tester le message attendu, la cause ou d'autres éléments relatifs à l'exception. Pour vérifier la cause de l'exception, j'utilise: expectedException.expectCause (Mockito.sameInstance (expectedException)) ou expectedException.expectCause (Mockito.instanceOf (MyException.class)) et quelques autres qui sont utiles.
Crenguta S

19

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

Utilisez simplement assertj

Utilisation d'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


a fonctionné pour moi ... Nous pouvons également vérifier le message d'exception.assertThatThrownBy (() -> myService.sumTingWong ("badArg")). hasMessage ("test") .isInstanceOf (IllegalArgumentException.class);
Sritam Jagadev

17

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, utilisez:

Mockito.doThrow(new AnyException()).when(obj).callAnyMethod();

16

Faites que l'exception se produise comme ceci:

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

Vérifiez que cela s'est produit soit en affirmant que votre test lèvera une telle exception:

@Test(expected = AnException.class)

Ou par une vérification simulée 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 depuis votre méthode de test).


L' verifyappel affirme-t-il l'exception?
NilsH

@NilsH Non. Mais à condition que la whenclause soit correcte, elle doit avoir levé une exception.
Duncan Jones

10

Utilisez doThrow de Mockito , puis attrapez l'exception souhaitée pour affirmer qu'elle a été levée 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);
}

5

En utilisant mockito, vous pouvez faire en sorte que l'exception se produise.

when(testingClassObj.testSomeMethod).thenThrow(new CustomException());

En utilisant Junit5, vous pouvez affirmer une exception, affirmer si cette exception est levée lors de l' appel de la méthode de test .

@Test
@DisplayName("Test assert exception")
void testCustomException(TestInfo testInfo) {
    final ExpectCustomException expectEx = new ExpectCustomException();

     InvalidParameterCountException exception = assertThrows(InvalidParameterCountException.class, () -> {
            expectEx.constructErrorMessage("sample ","error");
        });
    assertEquals("Invalid parametercount: expected=3, passed=2", exception.getMessage());
}

Trouvez un exemple ici: assert exception junit


Merci ! A travaillé pour moi
HariKishore

1

Sans rapport avec mockito, on peut attraper l'exception et affirmer ses propriétés. Pour vérifier que l'exception s'est produite, déclarez une condition fausse dans le bloc try après l'instruction qui lève l'exception.


La réponse @MariuszS répond correctement à ce que vous dites n'est pas lié à Mockito
pringi

@pringi Merci, je vois que la question concernait à la fois se moquer d'une exception et l'attraper. Je me demande cependant si cela dépend du comportement du code testé.
eel ghEEz

1

Ou si votre exception est levée depuis 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);  

}

-1

Message d'affirmation par exception:

    try {
        MyAgent.getNameByNode("d");
    } catch (Exception e) {
        Assert.assertEquals("Failed to fetch data.", e.getMessage());
    }

S'il est écrit comme ceci, quand il n'y a pas d' exception levée, le test réussira toujours . C'est ce que nous voulons éviter en premier lieu
Christian Lim
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.