Ich arbeite an einem Projekt, in dem klasseninterne Aufrufe üblich sind, die Ergebnisse jedoch oft einfache Werte sind. Beispiel ( kein echter Code ):
public boolean findError(Set<Thing1> set1, Set<Thing2> set2) {
if (!checkFirstCondition(set1, set2)) {
return false;
}
if (!checkSecondCondition(set1, set2)) {
return false;
}
return true;
}
Unit-Tests für diese Art von Code zu schreiben ist wirklich schwierig, da ich nur das Konditionssystem testen möchte und nicht die Implementierung der tatsächlichen Bedingungen. (Ich mache das in getrennten Tests.) In der Tat wäre es besser, wenn ich Funktionen bestanden hätte, die die Bedingungen implementieren, und in Tests gebe ich einfach ein wenig Schein. Das Problem bei diesem Ansatz ist das Rauschen: Wir verwenden häufig Generika .
Eine funktionierende Lösung; Es ist jedoch wichtig, das getestete Objekt zum Spion zu machen und die Aufrufe der internen Funktionen zu verfälschen.
systemUnderTest = Mockito.spy(systemUnderTest);
doReturn(true).when(systemUnderTest).checkFirstCondition(....);
Hier besteht die Sorge, dass die Implementierung des SUT effektiv geändert wird und es problematisch sein kann, die Tests mit der Implementierung synchron zu halten. Ist das wahr? Gibt es bewährte Methoden, um dieses Chaos interner Methodenaufrufe zu vermeiden?
Beachten Sie, dass es sich um Teile eines Algorithmus handelt. Daher ist es möglicherweise keine gewünschte Entscheidung, ihn auf mehrere Klassen aufzuteilen.
quelle
Wenn beide
findError()
undcheckFirstCondition()
usw. öffentliche Methoden Ihrer Klasse sind,findError()
handelt es sich tatsächlich um eine Fassade für Funktionen, die bereits über dieselbe API verfügbar sind. Daran ist nichts auszusetzen, aber es bedeutet, dass Sie Tests schreiben müssen, die den bereits vorhandenen Tests sehr ähnlich sind. Diese Vervielfältigung spiegelt einfach die Vervielfältigung in Ihrer öffentlichen Oberfläche wider. Das ist kein Grund, diese Methode anders zu behandeln als andere.quelle
Unit-Tests sollten den Vertrag testen; Für sie ist es das einzig Wichtige. Das Testen von Dingen, die nicht Bestandteil des Vertrags sind, ist nicht nur Zeitverschwendung, sondern auch eine potenzielle Fehlerquelle. Jedes Mal, wenn ein Entwickler die Tests ändert, wenn er ein Implementierungsdetail ändert, sollten Alarmglocken läuten. Dieser Entwickler kann (ob absichtlich oder nicht) seine Fehler verbergen. Das bewusste Testen von Implementierungsdetails erzwingt diese schlechte Angewohnheit, wodurch die Wahrscheinlichkeit steigt, dass Fehler ausgeblendet werden.
Die internen Aufrufe sind ein Implementierungsdetail und sollten nur für die Messung der Leistung von Interesse sein . Welches ist in der Regel nicht die Aufgabe von Unit-Tests.
quelle
a
einen Aufruf von methodb
in derselben Klasse enthält,a
müssen tests of tests of enthaltenb
. Und es gibt keine Möglichkeit, dies zu ändern, solangeb
es nichta
als Parameter übergeben wird. Aber ich verstehe, dass es keine andere Lösung gibt.b
es ein Teil der öffentlichen Schnittstelle ist, sollte es trotzdem getestet werden. Wenn nicht, muss es nicht getestet werden. Wenn Sie es öffentlich gemacht haben, nur weil Sie es testen wollten, haben Sie es falsch gemacht.Erstens frage ich mich, was an der von Ihnen geschriebenen Beispielfunktion schwer zu testen ist. Soweit ich sehen kann, können Sie einfach verschiedene Eingaben übergeben und überprüfen, ob der richtige Boolesche Wert zurückgegeben wird. Was vermisse ich?
Was Spione betrifft, so ist die Art des sogenannten "White-Box" -Tests, bei dem Spione und Spott verwendet werden, um Größenordnungen arbeitsintensiver, nicht nur, weil so viel mehr Testcode zu schreiben ist, sondern zu jedem Zeitpunkt, an dem die Implementierung stattfindet geändert, müssen Sie auch die Tests ändern (auch wenn die Schnittstelle gleich bleibt). Diese Art von Tests ist auch weniger zuverlässig als Black-Box-Tests, da Sie sicherstellen müssen, dass der gesamte zusätzliche Testcode korrekt ist und Sie darauf vertrauen können, dass Black-Box-Unit-Tests fehlschlagen, wenn sie nicht mit der Schnittstelle übereinstimmen Sie können dem nicht vertrauen, wenn es um die Überbeanspruchung von Mocks mit Code geht, da der Test manchmal nicht einmal viel echten Code testet - nur Mocks. Wenn die Mocks nicht korrekt sind, ist es wahrscheinlich, dass Ihre Tests erfolgreich sind, Ihr Code jedoch weiterhin fehlerhaft ist.
Jeder, der Erfahrung mit White-Box-Tests hat, kann Ihnen sagen, dass es Ihnen schwerfällt, diese zu schreiben und zu pflegen. Zusammen mit der Tatsache, dass sie weniger zuverlässig sind, sind White-Box-Tests in den meisten Fällen einfach weit unterlegen.
quelle