Mockito Wie kann man eine ausgelöste Ausnahme verspotten und geltend machen?

136

Ich benutze Mockito in einem Junit-Test. Wie kann man eine Ausnahme auslösen und dann behaupten, dass sie vorliegt (generischer Pseudocode)?

Paketüberfluss
quelle

Antworten:

75

BDD Style Solution (auf Java 8 aktualisiert)

Mockito allein ist nicht die beste Lösung für die Behandlung von Ausnahmen. Verwenden Sie Mockito mit Catch-Exception

Mockito + Catch-Exception + AssertJ

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

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

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

Beispielcode

Abhängigkeiten

MariuszS
quelle
2
Was ist "Fangausnahme"? Hast du einen Link?
Duncan Jones
was ist caughtException?
Saif Masadeh
Verstanden, es kommt voncom.googlecode.catchexception.CatchException.caughtException;
Saif Masadeh
211

Um Ihre zweite Frage zuerst zu beantworten. Wenn Sie JUnit 4 verwenden, können Sie Ihren Test mit Anmerkungen versehen

@Test(expected=MyException.class)

zu behaupten, dass eine Ausnahme aufgetreten ist. Und um eine Ausnahme mit Mockito zu "verspotten", verwenden Sie

when(myMock.doSomething()).thenThrow(new MyException());
NilsH
quelle
2
Dieser Ansatz ist nicht akzeptabel, wenn Sie die Methode eines Objekts mit einem bestimmten Status testen. Beispielsweise gibt es eine Objektmethode, die eine Ausnahme auslöst, wenn Sie sie zum zweiten Mal aufrufen. Und Sie müssen testen, um zu testen, ob beim zweiten Methodenaufruf eine Ausnahme ausgelöst wird, nicht beim ersten. Wenn beim ersten Methodenaufruf (in der Vorbereitungsphase) MyException ausgelöst wird, sollte der Test fehlschlagen. Mit diesem Ansatz können wir jedoch nicht überprüfen, bei welchem ​​Methodenaufruf die Ausnahme ausgelöst wird.
Sneg
In diesem Fall können wir jedoch eine Ausnahme vom ersten Methodenaufruf abfangen und in RuntimeException einschließen.
Sneg
28

Wenn Sie auch die Ausnahmemeldung testen möchten, können Sie die ExpectedException von JUnit mit Mockito verwenden:

@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
quelle
given()woher kommt das?
Mohammad Faisal
Ich bevorzuge auch die Verwendung der @Rule, da ich auf diese Weise auf erwartete Nachrichten oder Ursachen oder andere Dinge im Zusammenhang mit der Ausnahme testen kann. Zum Überprüfen der Ursache der Ausnahme verwende ich: expectedException.expectCause (Mockito.sameInstance (expectedException)) oder expectedException.expectCause (Mockito.instanceOf (MyException.class)) und einige andere, die sich als nützlich erweisen.
Crenguta S
19

Aktualisierte Antwort für den 19.06.2015 (wenn Sie Java 8 verwenden)

Verwenden Sie einfach assertj

Verwenden von assertj-core-3.0.0 + Java 8 Lambdas

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

Referenz: http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html

Selwyn
quelle
hat für mich funktioniert ... Auch wir können die Ausnahmemeldung überprüfen.assertThatThrownBy (() -> myService.sumTingWong ("badArg")). hasMessage ("test") .isInstanceOf (IllegalArgumentException.class);
Sritam Jagadev
17

Wenn Sie JUnit 4 und Mockito 1.10.x verwenden, kommentieren Sie Ihre Testmethode mit:

@Test(expected = AnyException.class)

und um Ihre gewünschte Ausnahme zu werfen, verwenden Sie:

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

Machen Sie die Ausnahme so:

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

Stellen Sie sicher, dass dies geschehen ist, indem Sie behaupten, dass Ihr Test eine solche Ausnahme auslöst:

@Test(expected = AnException.class)

Oder durch normale Scheinüberprüfung:

verify(obj).someMethod();

Die letztere Option ist erforderlich, wenn Ihr Test beweisen soll, dass Zwischencode die Ausnahme behandelt (dh die Ausnahme wird von Ihrer Testmethode nicht ausgelöst).

Duncan Jones
quelle
Bestätigt der verifyAufruf die Ausnahme?
NilsH
@NilsH Nein. Vorausgesetzt, die whenKlausel ist korrekt, muss sie eine Ausnahme ausgelöst haben.
Duncan Jones
10

Verwenden Sie Mockitos doThrow und fangen Sie dann die gewünschte Ausnahme ab, um zu bestätigen, dass sie später ausgelöst wurde.

@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
quelle
5

Mit mockito können Sie die Ausnahme auslösen.

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

Junit5 verwenden, können Sie Ausnahme geltend machen, behauptet , ob die Ausnahme ausgelöst wird , wenn Verfahren Prüfung aufgerufen wird.

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

Hier finden Sie ein Beispiel: Assert Exception Junit

Anupama Boorlagadda
quelle
Vielen Dank ! Arbeitete für mich
HariKishore
1

Unabhängig von Mockito kann man die Ausnahme abfangen und ihre Eigenschaften geltend machen. Um zu überprüfen, ob die Ausnahme aufgetreten ist, setzen Sie nach der Anweisung, die die Ausnahme auslöst, eine falsche Bedingung im try-Block.

Aal ghEEz
quelle
@MariuszS Antwort beantwortet richtig, was Sie sagen, hat nichts mit Mockito zu
tun
@pringi Danke, ich sehe, dass es bei der Frage darum ging, eine Ausnahme zu verspotten und zu fangen. Ich frage mich jedoch, ob dies von einem Verhalten des zu testenden Codes abhängt.
Aal Gheez
1

Oder wenn Ihre Ausnahme vom Konstruktor einer Klasse ausgelöst wird:

@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
quelle
-1

Durch Ausnahmemeldung bestätigen:

    try {
        MyAgent.getNameByNode("d");
    } catch (Exception e) {
        Assert.assertEquals("Failed to fetch data.", e.getMessage());
    }
Sam
quelle
Wenn dies so geschrieben ist und keine Ausnahme ausgelöst wird, besteht der Test trotzdem . Welches ist, was wir in erster Linie vermeiden wollen
Christian Lim