Mockito Jak kpić i potwierdzać rzucony wyjątek?

136

Używam mockito w teście junit. Jak zrobić wyjątek, a następnie potwierdzić, że ma (ogólny pseudokod)

przepełnienie stosu
źródło

Odpowiedzi:

75

Rozwiązanie w stylu BDD (zaktualizowane do Java 8)

Samo Mockito nie jest najlepszym rozwiązaniem do obsługi wyjątków, używaj Mockito z Catch-Exception

Mockito + Catch-Exception + AssertJ

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

when(() -> myService.foo());

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

Przykładowy kod

Zależności

Mariusz S.
źródło
2
Co to jest „wyjątek przechwytywania”? Masz link?
Duncan Jones
co jest caughtException?
Saif Masadeh
Rozumiem, pochodzi zcom.googlecode.catchexception.CatchException.caughtException;
Saif Masadeh
212

Najpierw odpowiedz na twoje drugie pytanie. Jeśli używasz JUnit 4, możesz oznaczyć swój test adnotacją

@Test(expected=MyException.class)

aby potwierdzić, że wystąpił wyjątek. Aby „wyszydzić” wyjątek z mockito, użyj

when(myMock.doSomething()).thenThrow(new MyException());
NilsH
źródło
2
takie podejście jest niedopuszczalne w przypadku, gdy testujesz metodę obiektu, który ma pewien stan. Na przykład istnieje metoda obiektu, która zgłasza wyjątek, jeśli wywołasz ją po raz drugi. I musisz przetestować, aby sprawdzić, czy zgłasza wyjątek podczas drugiego wywołania metody, a nie pierwszego. Jeśli wyrzuci MyException podczas pierwszego wywołania metody (na etapie przygotowania), to powinien zakończyć test. Ale przy takim podejściu nie jesteśmy w stanie sprawdzić, podczas którego wywołania metody jest generowany wyjątek.
Sneg
Chociaż w tym przypadku możemy złapać wyjątek od pierwszego wywołania metody i zawinąć go w RuntimeException.
Sneg
29

Jeśli chcesz również przetestować komunikat o wyjątku, możesz użyć ExpectedException JUnit z 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"));
}
Daniel Treiber
źródło
given()Skąd to pochodzi?
Mohammad Faisal,
Wolę również używać @Rule, ponieważ w ten sposób mogę przetestować oczekiwany komunikat lub przyczynę lub inne rzeczy związane z wyjątkiem. Aby sprawdzić przyczynę wyjątku, używam: spodziewanegoException.expectCause (Mockito.sameInstance (spodziewanyException)) lub spodziewanegoException.expectCause (Mockito.instanceOf (MyException.class)) i kilku innych, które mogą się przydać.
Crenguta S
19

Zaktualizowana odpowiedź na 19.06.2015 (jeśli używasz java 8)

Po prostu użyj assertj

Korzystanie z assertj-core-3.0.0 + Java 8 Lambdas

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

Źródła: http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html

Selwyn
źródło
zadziałało dla mnie ... Również możemy sprawdzić komunikat wyjątku.assertThatThrownBy (() -> myService.sumTingWong ("badArg")). hasMessage ("test") .isInstanceOf (IllegalArgumentException.class);
Sritam Jagadev
17

Jeśli używasz JUnit 4 i Mockito 1.10.x Opisz swoją metodę testową:

@Test(expected = AnyException.class)

i aby rzucić żądane użycie wyjątku:

Mockito.doThrow(new AnyException()).when(obj).callAnyMethod();
Prashant Kumar
źródło
16

Zrób wyjątek w ten sposób:

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

Sprawdź, czy to się stało, albo potwierdzając, że Twój test zgłosi taki wyjątek:

@Test(expected = AnException.class)

Lub przez normalną weryfikację próbną:

verify(obj).someMethod();

Ta ostatnia opcja jest wymagana, jeśli test ma na celu udowodnienie, że kod pośredni obsługuje wyjątek (tj. Wyjątek nie zostanie wyrzucony z metody testowej).

Duncan Jones
źródło
Czy verifywywołanie stwierdza wyjątek?
NilsH
@NilsH Nie. Ale jeśli whenklauzula jest poprawna, musiała zgłosić wyjątek.
Duncan Jones
10

Użyj doThrow Mockito, a następnie złap żądany wyjątek, aby potwierdzić, że został wyrzucony później.

@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);
}
Rodrigo Martins de Oliveira
źródło
5

Używając mockito, możesz zrobić wyjątek.

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

Korzystając z Junit5, możesz potwierdzić wyjątek, sprawdzić , czy ten wyjątek jest generowany podczas wywoływania metody testing .

@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());
}

Znajdź przykład tutaj: assert wyjątek junit

Anupama Boorlagadda
źródło
Dzięki ! Pracował dla mnie
HariKishore
1

W przeciwieństwie do mockito, można wychwycić wyjątek i potwierdzić jego właściwości. Aby sprawdzić, czy wyjątek się wydarzył, potwierdź fałszywy warunek w bloku try po instrukcji, która zgłasza wyjątek.

eel ghEEz
źródło
Odpowiedź @MariuszS poprawnie odpowiada na to, co mówisz, nie ma związku z Mockito
pringi
@pringi Dzięki, widzę, że pytanie dotyczyło zarówno kpienia z wyjątku, jak i przechwytywania go. Zastanawiam się jednak, czy to zależy od jakiegokolwiek zachowania testowanego kodu.
ghEEz węgorza
1

Lub jeśli twój wyjątek jest wyrzucany z konstruktora klasy:

@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);  

}
JediCate
źródło
-1

Potwierdź przez komunikat wyjątku:

    try {
        MyAgent.getNameByNode("d");
    } catch (Exception e) {
        Assert.assertEquals("Failed to fetch data.", e.getMessage());
    }
Sam
źródło
Jeśli zostanie napisane w ten sposób, gdy nie zostanie zgłoszony wyjątek, test nadal będzie przebiegał pomyślnie . Tego właśnie chcemy uniknąć w pierwszej kolejności
Christian Lim