Trick 17 mit JUnit

vergleich1.png

Nehmen wir an, wir hätten eine Klasse FileProvider, die mittels der Methoden getFile() File-Instanzen zurückgibt, deren Pfad bestimmte Eigenschaften erfüllen muss. Im folgenden Test prüfen wir eine dieser Eigenschaften ab:


public void testFilePath() {
FileProvider fileProvider = new FileProvider();
assertEquals("path/myfile.txt", fileProvider.getFile());
}

Wenn jetzt der verwendete FileProvider im einfachsten Fall wie folgt implementiert ist:


class FileProvider {
public File getFile() {
return new File("path/myfile.txt");
}
}

schlägt der Test trotzdem fehl:

junit.framework.AssertionFailedError: expected:<path/myfile.txt> but was:<path/myfile.txt>

und man verbringt eine harte Zeit, sich klarzumachen, was gerade wirklich passiert ist.

Die Lösung liegt in der verwendeten assertEquals-Methode und der Implementierung der toString()-Methode im File-Typ. Anstatt, wie eigentlich vorgesehen, zwei String-Objekte zu vergleichen, werden mit der obigen assertEquals-Methode zwei Objects, konkret ein String als Soll-Instanz und ein File als Ist-Instanz, miteinander verglichen. Dieser Vergleich geht schon wegen der verschiedenen Instanztypen schief. Die Ausgabe basiert allerdings auf dem Ergebnis, das die jeweilige toString()-Methode zurückgibt. Und da geben beide Instanzen die gleiche Zeichenkette zurück, was zu der obigen, sehr mißverständlichen Fehlermeldung führt.

Ich hätte dazu zwei Verbesserungsvorschläge:

  • Die Fehlermeldung so umbauen, dass sie die verschiedenen Typen der Objekte zeigt, wenn die Gleichheitsprüfung am Typ der Objekte gescheitert ist (das könnte mit der gegenwärtigen Struktur der equals()-Methoden etwas schwieriger werden) und nur dann auf die Darstellung der Instanzwerte (über toString()) zurückgreift, wenn die Prüfung daran scheiterte.
  • Eine zusätzliche Methode definieren, die ebenfalls eine textuelle Objektrepräsentation zurückgibt und, falls sie vorhanden ist, von JUnit anstelle von toString() aufgerufen wird. Also eine toJUnitString() oder so ähnlich. Ist sie nicht definiert, wird weiterhin toString() verwendet. Im meinem Fall hätte dieser Vorschlag also nichts geholfen.

Was wären weitere Möglichkeiten?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s