“Ein entschlossener Mensch wird mit einem Schraubenschlüssel mehr anzufangen wissen als ein unentschlossener mit einem Werkzeugladen.“
Emil Oesch
Mit JUnit 4.4 wurde die Hamcrest Bibliothek über die unscheinbare Methode assertThat
Bestandteil des Test Frameworks. Obwohl schon einige Zeit vergangen ist, haben viele Entwickler das Potential dieser Ergänzung noch nicht entdeckt.
Bislang werden in den Unit Test die aktuellen Werte gegen die zu erwartenden Werte geprüft. Am beliebtesten sind da die Methoden assertEquals
und assertTrue
.
assertEquals("Hello World", object.toString()); assertTrue(file.exists());
In der ersten Zeile wird geprüft ob das Resultat der Methode
mit dem Erwartungswert übereinstimmt und in der zweiten Zeile wird geprüft ob der übergebene Ausdruck toString
zurückliefert. Neben diesen beiden Methoden gibt es noch eine lange Liste weiterer Methoden, die unter anderen Arrays und Collections auf Gleichheit, Objekte auf Identität und reelle Zahlen auf einen Näherungswert testen. Zur besseren Lesbarkeit werden die true
assert
Methoden über einen statischen Import eingefügt und der Klassenname Assert
kann entfallen.
Der Ansatz bei der assertThat
Methode ist ein anderer, hier wird ein Matcher gegen das aktuelle Objekt ausgewertet. Die Schnittstelle ist sehr flexibel und erlaub eine Vielzahl von Prüfungen auf dem Objekt.
assertThat(object.toString(), is(equalTo("Hello World")); assertThat(file, exists());
Bei dieser Methode steht das zu testende Objekt links und der Ausdruck, der erfüllt werden muss auf der linken Seite. In der ersten Zeile wird mit dem equalTo
Matcher geprüft, ob die Methode den Ausdruck Hello World liefert und in den zweiten Zeile wird mit einem selbstgeschriebenen Matcher die Existenz der Datei geprüft. Wenn man sich eine bessere Lesbarkeit wünscht, kann man wie oben geschehen den Matcher is
einfügen.
Neben der guten Lesbarkeit und der Erweiterbarkeit trumpft der Matcher Ansatz aber noch mit einigen weiteren Vorteilen auf. Die Matcher sind typsicher und miteinander kombinierbar. Im folgenden sind die assertEquals
und die assertThat
im fehlerhaften Einsatz. Während assertEquals
unerkannt einen falschen Vergleich durchführt, kann der assertThat
Ausdruck erst gar nicht kompilieren.
assertEquals(object.hashCode(), "HelloWorld"); assertThat(object.hashCode(), equalTo("Hello World"));
Die Matcher können auf viele Arten miteinander kombiniert werden. Eine sehr einfache Kombination ist die Verwendung des not
Matchers oder die Anwendung eines Matchers auf eine Liste.
assertThat(file, not(exists())); assertThat(listOfFiles, everyItem(exists()); assertThat(listOfFiles, hasItem(exists());
In der ersten Zeile wird geprüft, ob die Datei nicht existiert und in den beiden anderen Zeilen, ob jede Datei in der Liste oder mindestens eine Datei existiert. Häufig müssen mehrere Bedingungen auf einer Instanz geprüft werden, auch solche Prüfungen sind mit den bereitgestellten Matchern leicht formulierbar:
assertThat(marxBrother, anyOf(chico, harpo, groucho, gummo, zeppo)); assertThat(subject, either(pinky).or(brain));
Und wem die vorhandenen Matcher nicht ausreichen, der kann sich recht einfach eigene schreiben. Der oben vorgestellte exists
Matcher könnte wie folgt formuliert werden.
public static Matcher<Path> exists() { return new FeatureMatcher<Path, Boolean>(Matchers.is(true), "exists", "exists") { @Override protected Boolean featureValueOf(Path actual) { return Files.exists(actual); } }; }
Die statische Methode exists
liefert einen FeatureMatcher
, der für ein Path
Objekt true
zurückliefert, wenn die Datei existiert, ansonsten false
.
Abschließend kann man allen Entwicklern die Verwendung der assertThat
Methode und des Hamcrest Framework nur wärmsten ans Herz legen. Die Kombinierbarkeit und Erweiterbarkeit der Matcher führt zu übersichtlichen, kompakt formulierten Unit Test, die Entwicklungs- und Einarbeitungszeit sparen.