Möchte man das auftreten von Exceptions mit JUnit testen, so gibt es verschiedene Wege und Möglichkeiten. Die bekanntesten sind sicherlich
@Test(expected=IllegalArgumentException.class) public void methodThrowsException() { subjectUnderTest.foo(someIllegalArgument); }
und
@Rule public ExpectedException thrown = ExpectedException.none(); @Test public void methodThrowsException() { thrown.expect(IllegalArgumentException.class); subjectUnderTest.foo(someIllegalArgument); }
Beide Varianten haben den Nachteil, dass die Given-When-Then (oder Arrange-Act-Assert) Reihenfolge aufgebrochen wird, so dass man häufig „von Hand“ geschriebenen Code wie den folgenden findet:
@Test public void methodThrowsException() { try { subjectUnderTest.foo(someIllegalArgument); fail("IllegalArgumentException expected, but not thrown!"); } catch (IllegalArgumentException ex) { assertThat(ex.getMessage(), is("foobarfoo")); } }
Jetzt sind die Anweisungen zwar wieder in der Given-When-Then Reihenfolge, aber die try-catch-Anweisungen machen den Code unübersichtlich.
Die folgende Lösung ist uns in den Sinn gekommen, nachdem wir uns im aktuellen Projekt über Clean Code ausgetauscht haben:
@Test public void methodThrowsException() { IllegalArgumentException ex = foo(someIllegalArgument); assertThat(ex.getMessage(), is("foobarfoo")); } private Exception foo(FooBarFoo fooBarFoo) { try { subjectUnderTest.foo(someIllegalArgument); return null; } catch (IllegalArgumentException ex) { return ex; } }
Der Testcode ist sauber, die Reihenfolge der Testanweisungen stimmt und es sind keine Erweiterungen wie @Rules oder catch-excpetion notwendig.