ExpectedException
funktioniert, indem Sie Ihre gesamte Testmethode über eine JUnit @Rule in einen Try-Catch-Block einschließen . Wenn Ihr Code eine Ausnahme auslöst, geht er den Stapel zum nächsten try / catch hoch, 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 erfasste Ausnahme in einer Methode auftritt, kehrt das Steuerelement später in dieser Methode niemals zu Anweisungen zurück. Hier gelten die gleichen Regeln: Control kehrt nach der Ausnahme nie mehr zu den Anweisungen in Ihrem Test zurück.
Technisch gesehen könnten Sie die Überprüfungen in einen endgültigen Block setzen, aber das ist in der Regel eine schlechte Angewohnheit . BEARBEITEN: Ihr zu testendes System löst möglicherweise eine unerwartete oder gar keine Ausnahme aus, die Ihnen eine hilfreiche Fehlermeldung und Ablaufverfolgung liefert. Wenn dieser Fehler jedoch dazu führt, dass Ihre Überprüfungen oder Zusicherungen im finally
Block fehlschlagen , 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 Grundursache des Fehlers folgen, was fälschlicherweise bedeutet, dass der darüber liegende Code erfolgreich war.
Wenn Sie den Status nach der Ausnahme wirklich pro Methode ü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(...));
}
Update: Mit den Lambda-Ausdrücken von Java 8 können Sie einen Funktionsschnittstellenaufruf so kurz in einen try-Block einbinden, dass er nützlich ist . Ich kann mir vorstellen, dass die Unterstützung dieser Syntax in viele Standardtestbibliotheken Eingang findet.
assertThrows(MyException.class,
() -> systemUnderTest.throwingMethod());
finally
Block die Ausnahme verschlucken?finally
fängt die Ausnahme nicht ab, daher wird sie an den Wrapper weitergegeben. Siehe Kevin Welkers Antwort; das funktioniert gut.finally
Block darstellt , wodurch Sie keine unerwarteten Ausnahmen sehen und debuggen können, die die zu testende Methode möglicherweise auslöst. Diese unerwartete Ausnahme ist die verschluckte, die ich meine.Elegantere Lösung mit Fangausnahme
@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(...)); }
quelle
then(caughtException())
ist? Ich muss davon ausgehen, dasswhen
undverify
tatsächlichMockito.when
undMockito.verify
aber Sie nicht die Klasse vonthen.
Sobald die Ausnahme in UT ausgelöst wird, wird der gesamte darunter liegende Code 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 try with finally verwenden .
@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(...)); } }
quelle
Ich habe dies noch nicht versucht, aber zusätzlich zu Jeff Bowmans hervorragender Antwort haben Sie möglicherweise die Wahl, die ExpectedException-Regel mit einem try ... finally-Konstrukt zu verwenden und Ihre Verifizierungsanweisung in den finally-Block zu setzen.
quelle