16. Dezember 2015 | 3 min lesezeit

Exception Testing

Eine der Herausforderungen für die Erstellung von Unit Tests besteht in der Identifikation und Behandlung der Randfälle. Einen wichtigen Stellenwert haben hier wiederum die unbehandelten Exceptions, da diese nicht selten zu unvorhergesehenen Programmabbrüchen führen können. Ein expliziter Test auf Exceptions ist daher immer empfehlenswert und erhöht dadurch die Qualität des Programmcodes.

JUnit bietet eine Reihe von Möglichkeiten wie Fehlerfälle getestet werden können. Neben dem klassischen Ansatz mittels Try-Catch und dem Expected-Parameter der Test Annotation bietet JUnit mit der ExpectedException Rule schon selber drei Varianten an. Dazu steht seit der Einführung von Lambda-Expressions in Java 8 eine weitere Option zur Verfügung.

Try-Catch Blöcke

Der klassische Ansatz, der schon zu Zeiten von JUnit3 funktionierte, greift auf das Try-Catch Statement zurück. Dabei wird die zu testende Methode in einem Try-Block aufgerufen und die erwartete Exception im Catch-Block gefangen, wo sie detailliert geprüft werden kann. Ein fail() im Try-Block stellt sicher, dass die erwartete Exception geworfen wird und der Test fehlschlägt, falls bei der Ausführung keine Exception aufgetreten ist.

Da die Exception im Catch-Block behandelt wird, besteht die Möglichkeit weitere Methodenaufrufe oder Assertions auszuführen. So lässt sich bei einem Mock oder Spy der Aufruf einer bestimmten Methode verifizieren. Es ist jedoch zu bedenken, dass auch für Unit-Tests das Single-Responsibility-Prinzip gilt.

@Test(expected=…)

Der Expected-Parameter legt den erwarteten Exception-Typ für einen Test fest. Da jedoch keine detaillierteren Informationen über die Exception abgeprüft werden können, ist es nicht möglich zu erkennen, an welcher Stelle die Exception ausgelöst wurde. Wird die Exception beispielsweise bereits während der Testvorbereitung (@Before) geworfen, gilt der Test trotzdem als erfolgreich. Dies kann zu einem echten Problem werden, da der Test den tatsächlich Fehler verschleiert und dem Entwickler ein falsches Gefühl der Sicherheit vermittelt.

ExpectedException Rule

Mit Version 4.7 wurde in JUnit das Konzept der Rules eingeführt. Eine Rule legt sich ähnlich wie ein Interceptor um die ausgeführte Testmethode und führt noch vor dem Setup (@Before) bzw. nach dem TearDown (@After) Code aus. Mit der ExpectedException Rule bietet JUnit eine weitere Variante für das Testen von Fehlerfällen. Im Unterschied zum Expected-Parameter der Test Annotation können mit der Rule auch weitere Details einer Exception geprüft werden. Zu beachten ist, dass der Test beim ersten Auftreten einer Exception abgebrochen wird und alle folgenden Zeilen niemals durchlaufen werden.

AssertJ und Java 8

Die in Java 8 eingeführten Lambda-Expressions eröffnen Entwicklern vielfälltige Möglichkeiten – auch bei der Erstellung von Tests und im speziellem beim Prüfen von Fehlerfällen. So stellt beispielsweise das bereits in einem vorangegangenen Blog-Beitrag vorgestellte Testframework AssertJ eine Variante zur Verfügung.

Wie im Beispiel zu sehen, kommt dieser Ansatz ohne Extras aus und führt dank der Fluent-API zu einem gut lesbaren Test, der eine detaillierte Überprüfung der aufgetretenen Exceptions durch die von AssertJ angebotenen Matcher erlaubt. Darüber hinaus besteht wie bei der klassischen try-catch-Variante die Möglichkeit weitere Methodenaufrufe auszuführen. Wer nun die Vorteil der Lambda-Variante nutzen, allerdings auf AssertJ verzichten möchte, sollte sich diesen Artikel ansehen.


Keine Kommentare

Kontakt

OPEN KNOWLEDGE GmbH

Standort Oldenburg:
Poststraße 1, 26122 Oldenburg

Standort Essen:
II. Hagen 7, 45127 Essen