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


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


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

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

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


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

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).


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

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


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.


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

}

-1

Durch Ausnahmemeldung bestätigen:

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

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.