Sollte ich hashCode / equals / toString testen?

8

Beim Schreiben von Java-Klassen ist es nicht ungewöhnlich, Methoden mit Ihrer IDE zu erstellen, wie z. B.

  • toString()
  • equals()
  • hashCode()

Aber sobald Sie sie mit der IDE generiert haben, werden sie Teil Ihrer Codebasis (in SCM) und daher gelten alle Qualitätsmessmittel.

Besonders die equals- und hashcode-Methoden enthalten viele Bedingungen. Wenn ich keine Komponententests schreibe, ist die Punktzahl für die Codeabdeckung (Zeilen-, Bedingungs-, Mutations-) ziemlich niedrig, besonders wenn die zu testende Klasse nicht so groß ist.

Einige Coverage-Tools unterstützen das Filtern (d. h. cobertura), andere (d. h. jacoco) nicht. Aber die Coverage-Tools offenbaren nur ein Symptom - ungeprüften Code - und deshalb frage ich nicht, ob ich das Symptom unterdrücken / ignorieren soll, sondern wie ich mit der Ursache umgehen soll.

Frage ist: Soll ich Komponententests für diese Methoden schreiben?

  • Wenn ja, was sind gute Gründe dafür? Und was ist ein vernünftiger Ansatz?
  • Wenn nein, warum nicht?

Ich frage nicht nach generierten Klassen wie JAXB pojos, WS-Clients usw., die einfach automatisch generiert und von der Coverage-Analyse ausgeschlossen werden können.

    
Gerald Mücke 21.03.2017, 13:57
quelle

4 Antworten

8

Wenn Sie diese Methoden generieren, sollten Sie wahrscheinlich auch die Tests dafür generieren ;-)

Es kann mühsam sein, diese Methoden von Hand zu testen, aber je nachdem, was Sie mit Ihren Tests sicherstellen möchten, könnte es sich lohnen, diese Methoden ebenfalls zu testen. Gegenfrage: Würden Sie Log-Statements testen?

Es hängt wirklich davon ab, was Sie erreichen wollen. Einige werden sagen: nicht, andere sagen: Tu es.

Über einige Gründe nachdenken, solche Methoden nicht zu testen:

  • Code wird generiert und kann viele Felder enthalten. das Testen könnte zu vielen verschiedenen Kombinationen führen, die nur mühsam zu schreiben / zu warten wären und vielleicht wurde der Generator bereits gut genug getestet? ; -)
  • Sie erhalten keinen Wert, wenn Sie Tests dafür durchführen. Ihr toString() wird nur von Protokollen oder vom Debugger verwendet, so dass es Ihnen egal ist.
  • Sie vertrauen darauf, dass der generierte Code sicher genug für hashcode und equals ist

Gründe, solche Methoden zu testen:

  • um sicherzustellen, dass das Ergebnis wie erwartet ist
  • Sie möchten sicherstellen, dass beim Regenerieren dieser Methoden die vorherigen Methodenimplementierungsverwendungen nicht aufgehoben werden
  • Sie verwenden Ihre toString() -Methode neben der Protokollierung und möchten nicht, dass bestimmte Dinge dort angezeigt werden. Wie Hulk sagte, möchten Sie vielleicht auch sicherstellen, dass bestimmte Dinge nicht einmal in den Protokollen auftauchen.

Aber diese waren eher erfunden. In den letzten Projekten habe ich toString() und equals oder hashCode nur selten getestet, da dies nicht für notwendig erachtet wurde und alle einverstanden waren.

Es kann alles darauf hinauslaufen: Wie sicher soll Ihr Code sein und wie viel Wert ist es Ihnen (oder Ihrem Unternehmen oder Ihrem Kunden; -))

    
Roland 21.03.2017, 14:19
quelle
5

Das Problem mit IDE-generiertem hashCode / equals ist, dass es mit dem Objekt selbst nicht mehr synchron ist (zum Beispiel wenn Sie neue Felder hinzufügen). Ich würde daher raten, Tests für hashCode und equals zu erstellen.

Es wäre natürlich nicht optimal, diese von Hand zu schreiben. Sie können automatisierte Tools wie das Projekt EqualsVerifier verwenden, um diese zu einem Einzeiler zu machen.

toString ist ein anderes Biest, da es keinen Vertrag definiert hat. Wenn Sie toString nur verwenden, um ein besseres Debugging-Erlebnis zu erhalten, würde ich es nicht testen und es nur aus den Coverage-Berechnungen entfernen.

    
Karel Petranek 21.03.2017 14:16
quelle
1

Gleiches gilt für externe Bibliotheken - Sie sollten die Methoden equals und hashcode nicht testen, wenn Sie das generieren. Ein Plugin, das die Abdeckung überprüft, sollte einen Mechanismus haben, um diese erzeugten Quellen zu ignorieren.

Es gibt keinen guten Grund, generierten Code zu testen, keinen Unterschied, ob dies in Ihrer Klasse oder in der ganzen Klasse generiert wird.

Wenn Sie von einem externen Mechanismus abhängig sind, sollten Sie glauben, dass er richtig erstellt wurde.

    
ByeBye 21.03.2017 14:05
quelle
0

Diese Methoden sind für sich genommen nutzlos. Wenn Sie diese Klassen nicht in Sammlungen verwenden (wie HashSet / HashMap ) oder wenn Sie diese Klasseninstanzen nie auf Gleichheit prüfen, benötigen Sie keine Komponententests. Und in diesem Fall würde ich nur das Plugin deaktivieren, das sie erzeugt, wie @ByeBye vorgeschlagen.

Aber wenn Sie das tun, brauchen Sie Unit-Tests. Wenn eine falsche Implementierung zu einem Anwendungsfehler oder zu einem falschen Verhalten führen kann, muss diese Implementierung durch Komponententests abgedeckt werden.

    
esin88 21.03.2017 14:15
quelle