Mockito verifizieren nach Ausnahme Junit 4.10

Lesezeit: 4 Minuten

Ich teste eine Methode mit einer erwarteten Ausnahme. Ich muss auch überprüfen, ob ein Bereinigungscode (für ein verspottetes Objekt) aufgerufen wurde, nachdem die Ausnahme ausgelöst wurde, aber es sieht so aus, als würde diese Überprüfung ignoriert. Hier ist der Code. Ich benutze den Junit ExpectedException Rule um die erwartete Ausnahme zu überprüfen.

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

@Test
public void testExpectedException()
{
   MockedObject mockObj = mock(MockedObj.class);
   MySubject subject = new MySubject(mockedObj);
   expectedEx.expect(MyException.class);
   expectedEx.expectMessage("My exception message.");
   subject.someMethodThrowingException();
   verify(mockObj).
       someCleanup(eq(...));
}

Es scheint wie die verify wird total ignoriert. Egal welche Methode ich einsetze verifymein Test besteht, was ich nicht will.

Irgendeine Idee, warum das passiert?

Benutzer-Avatar
Jeff Bowmann

ExpectedException Werke von Verpackung Ihrer gesamten Testmethode in einem Try-Catch-Block über a JUnit @Rule. Wenn Ihr Code eine Ausnahme auslöst, geht er den Stack hinauf zum nächsten try/catch, der sich zufällig in der ExpectedException-Instanz befindet (die überprüft, ob es sich um die erwartete Ausnahme handelt).

Wenn in Java eine nicht abgefangene Ausnahme in einer Methode auftritt, kehrt die Steuerung nie zu Anweisungen später in dieser Methode zurück. Hier gelten die gleichen Regeln: Die Kontrolle kehrt nach der Ausnahme nie zu den Anweisungen in Ihrem Test zurück.

Technisch gesehen könnten Sie die Überprüfungen in einen finally-Block stecken, aber das ist es in der Regel eine schlechte Angewohnheit. BEARBEITEN: Ihr zu testendes System löst möglicherweise eine unerwartete Ausnahme oder überhaupt keine Ausnahme aus, wodurch Sie eine hilfreiche Fehlermeldung und Ablaufverfolgung erhalten würden. Wenn dieser Fehler jedoch dazu führt, dass Ihre Überprüfungen oder Behauptungen in der finally block, dann zeigt Java dies anstelle einer Meldung über die unerwartete Ausnahme oder den unerwarteten Erfolg an. Dies kann das Debuggen erschweren, insbesondere weil Ihr Fehler aus Codezeilen stammt, die der Hauptursache des Fehlers folgen, was fälschlicherweise impliziert, dass der Code darüber erfolgreich war.

Wenn Sie den Status nach der Ausnahme wirklich auf Methodenbasis überprüfen müssen, können Sie jederzeit zu dieser Redewendung zurückkehren:

@Test
public void testExpectedException()
{
  MockedObject mockObj = mock(MockedObj.class);
  MySubject subject = new MySubject(mockedObj);
  try {
    subject.someMethodThrowingException();
    fail("Expected MyException.");
  } catch (MyException expected) {
    assertEquals("My exception message.", expected.getMessage());
  }
  verify(mockObj).someCleanup(eq(...));
}

Aktualisieren: Mit den Lambda-Ausdrücken von Java 8 können Sie einen funktionalen Schnittstellenaufruf in einen Try-Block einschließen kurz genug, um nützlich zu sein. Ich kann mir vorstellen, dass die Unterstützung für diese Syntax ihren Weg in viele Standard-Testbibliotheken finden wird.

assertThrows(MyException.class,
    () -> systemUnderTest.throwingMethod());

  • Warum sollte die Überprüfung in a finally blockieren die Ausnahme schlucken? finally fängt die Ausnahme nicht ab, also wird sie an den Wrapper weitergegeben. Siehe Kevin Welkers Antwort; das funktioniert ganz gut.

    – Stefan Frie

    16. November 2018 um 14:45 Uhr

  • @StefanDeitmer Ich entschuldige mich dafür, dass ich es nicht gut artikuliert habe. Wenn Ihr Test besteht, ja, es wird gut funktionieren. Wenn der Test fehlschlägt, kann dies darauf zurückzuführen sein, dass keine Ausnahme ausgelöst wurde ODER die falsche Ausnahme ausgelöst wurde ODER dass ein Nachbedingungszustand fehlgeschlagen ist, über den die Antwort spricht. Das Problem ist, dass eine fehlgeschlagene Überprüfung darauf hinausläuft, eine Ausnahme in a auszulösen finally block, was Sie daran hindern würde, unerwartete Ausnahmen zu sehen und zu debuggen, die die zu testende Methode auslösen kann. Diese unerwartete Ausnahme ist die geschluckte, die ich meine.

    – Jeff Bowmann

    16. November 2018 um 15:44 Uhr

Sobald Exception in UT geworfen wird, wird der gesamte Code darunter ignoriert.

@Test(expected = Exception.class)
public void testExpectedException() {
   MockedObject mockObj = mock(MockedObj.class);
   MySubject subject = new MySubject(mockedObj);
   subject.doSomething(); // If this line results in an exception then all the code below this will be ignored.
   subject.someMethodThrowingException();
   verify(mockObj).
       someCleanup(eq(...));
}

Um dem entgegenzuwirken und alle getätigten Anrufe zu überprüfen, können wir verwenden Versuchen mit endlich.

@Test(expected = Exception.class)
    public void testExpectedException() {
          MockedObject mockObj = mock(MockedObj.class);
          MySubject subject = new MySubject(mockedObj);
          try {
               subject.someMethodThrowingException(); 
          } finally {
             verify(mockObj).
             someCleanup(eq(...));
          }
} 

Elegantere Lösung mit Fang-Ausnahme

@Test
public void testExpectedException()
{
    MockedObject mockObj = mock(MockedObject.class);
    MySubject subject = new MySubject(mockObj);

    when(subject).someMethodThrowingException();

    then(caughtException())
            .isInstanceOf(MyException.class)
            .hasMessage("My exception message.");

    verify(mockObj).someCleanup(eq(...));
}

  • Hallo, könnten Sie auf was eingehen then(caughtException()) ist? davon muss ich ausgehen when und verify sind eigentlich Mockito.when und Mockito.verify aber Sie geben nicht die Klasse von an then.

    – Navitron

    3. September 2018 um 8:13 Uhr

  • das war so etwas github.com/Codearte/catch-exception/blob/legacy/1.x/… , aber das ist jetzt veraltet. Versuchen Sie CatchException2 oder AssertJ

    – MariuszS

    4. September 2018 um 9:59 Uhr

Ich habe das noch nicht ausprobiert, aber zusätzlich zu Jeff Bowmans ausgezeichneter Antwort haben Sie möglicherweise die Wahl, die ExpectedException-Regel mit einem try… finally-Konstrukt zu verwenden, indem Sie Ihre Verify-Anweisung in den finally-Block einfügen.

1205650cookie-checkMockito verifizieren nach Ausnahme Junit 4.10

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy