Donnerstag, 31. Oktober 2013

JUnit Rules

Vor einiger Zeit bin ich zufällig über eine weniger bekannte Funktionalität von JUnit gestoßen: JUnit Rules.

Das Problem

Mit dem Rules Konstrukt verfügt JUnit seit einer ganzen Weile über die Möglichkeit, den Testablauf zu beeinflussen, also z.B. vor oder nach einem Test etwas zu tun.
Das klingt erstmal absolut unspannend, immerhin sind Methoden, die mit @Before und @After Annotationen versehen werden nicht gänzlich unbekannt. Also was soll das Ganze?

Versuchen wir es mal mit einem einfachen Beispiel:

Das Ergebnis davon sieht wenig überraschend wie folgt aus:

vor dem Test...
test
nach dem Test...


Nehmen wir an, uns gefällt was in den before() und after() Methoden passiert und wir möchten das wiederverwenden. Nichts einfacher als das:

Das Ergebnis der Ausführung dieser Klasse mit Hilfe von JUnit sieht wie folgt aus:

vor dem Test...
extended test
nach dem Test...
vor dem Test...
test
nach dem Test...


Durch Vererbung von JUnit Tests erhalten wir ein Verhalten, was nicht in jedem Fall gewünscht ist. Zunächst einmal werden alles Tests der Oberklasse ebenfalls ausgeführt. Des Weiteren haben wir keine Möglichkeit z.B. nur die before() Logik zu nutzen, ohne ebenfalls die Logik innerhalb der after() Methode auszuführen. Das Schränkt die Wiederverwendbarkeit stark ein und führt zu unübersichtlichen Klassenhierarchien.

Die Lösung: JUnit Rules

Mit Hilfe von JUnit Rules lässt sich das Problem elegent lösen. Die Rules stellen einen mit Interceptoren oder Aspekten vergleichbaren Mechanismus bereit unabhängig von der Klassenhierarchie zusätzliche Logik in den Testablauf einzubauen.

Wie funktioniert es? 

Um eine Rule zu definieren muss eine Klasse erstellt werden, die das Interface org.junit.rules.TestRule implementiert. Darin ist nur die Methode apply(Statement base, Description description) definiert. Hinter dem Statement-Objekt verbirgt sich der laufende JUnit Test welcher mit base.evaluate() ausgeführt werden kann. Davor und danach kann eigene Logik ausgeführt werden. Dies könnte z.B. wie folgt aussehen:

Um die Rule im eigenen JUnit Test verwenden zu können wird diese einfach als Klassenvariable instanziiert und mit der @Rule Annotation versehen:
Das Ergebnis des Tests sieht wie folgt aus:

vor dem Test...
test
nach dem Test...


Die Rule wird beim Aufruf jeder einzelner Test-Methode verwendet, analog zu @Before bzw. @After. Alternativ lässt sich die Rule einmalig für die Testklasse verwenden, hierfür ist nur die folgende Änderung notwendig:

JUnit bringt bereits einige vorgefertigte Rules mit, siehe https://github.com/junit-team/junit/wiki/Rules

Keine Kommentare:

Kommentar veröffentlichen