Unit-Test einer Leermethode

13

Um einen Fehler in einer Anwendung zu beheben, änderte ich eine benannte Methode, postLoginindem ich einer vorhandenen Methode namens einen Aufruf hinzufügte getShoppingCart.

Code

protected void postLogin() {
  getShoppingCart();
}

Ich bin mir jedoch nicht sicher, wie ich einen Unit-Test am besten schreiben kann postLogin.

Ansatz 1

Verwenden Sie verify from Mockito, um einfach zu überprüfen, ob die Methode aufgerufen wurde.

verify(mock).getShoppingCart();

Ansatz 2

Testen Sie die Nebenwirkung des Methodenaufrufs, indem Sie den Wert des Warenkorbs des Benutzers abrufen.

AssertNotNull(user.getShoppingCart());

Ist ein Ansatz besser als der andere?

A_B
quelle
1
Das erleichtert das Verständnis des Tests und hält den Code sauber. Wenn Sie sich bezüglich des Testdesigns nicht sicher sind, KÖNNTE dies auch ein Zeichen dafür sein, dass das Code-Design deaktiviert ist. Stellen Sie sicher, dass Sie die folgenden Fragen stellen: " WARUM behebt das Hinzufügen dieses Methodenaufrufs den Fehler? Ist dies der RICHTIGE Weg, um diesen Fehler zu beheben?"
Caleb
8
Sofern Ihre getShoppingCart()Methode keine Nebenwirkungen hat, müssen Sie nicht testen, ob sie aufgerufen wird. Wenn es Nebenwirkungen hat, sollten Sie seinen Namen wirklich ändern, da getXXX()Methoden herkömmlicherweise idempotent sein sollten.
Jules
@Jules getNextValue? Vielleicht könnte jemand sagen "Nenn es nicht Getter, ändere den Namen in nextValue", aber ich habe es schon mal gesehen getNext. Vielleicht wäre ein besseres Beispiel ein Objekt, das ein Elektron darstellt; was passiert , wenn ich anrufe getPosition? Oder schlimmergetPosition(); getVelocity();
Aaron

Antworten:

18

Normalerweise bevorzuge ich Methode 2.

Warum? Weil Sie postLogineinen bestimmten Status Ihres Systems ändern möchten , aber wie dies erreicht wird (und welche Methoden es intern dafür aufruft), ist nur ein Implementierungsdetail, über das Ihr Komponententest keine Annahmen machen sollte. Machen Sie Ihren Test also besser, indem Sie nur den Endzustand überprüfen.

Doc Brown
quelle
4

Ich würde getShoppingCart in so etwas wie initializeShoppingCart ändern. Der Zweck der Methode sollte für jeden klar sein, der sie liest, ohne überprüfen zu müssen, was die Methode tut, und Nebenwirkungen wie diese können für Benutzer der Methode ein überraschendes Verhalten hervorrufen.

Wenn getShoppingCart in einer anderen Klasse ist und die Einheit bereits getestet wurde, würde ich Ansatz 1 verwenden - es ist nicht erforderlich, erneut zu testen, was bereits getestet wurde. In diesem Fall sind wir sicher, dass getShoppingCart ordnungsgemäß funktioniert, und wir möchten nur sicherstellen, dass es von postLogin aufgerufen wird. Wenn also in Zukunft jemand diesen Aufruf entfernt, schlägt der Test fehl.

Wenn getShoppingCart eine private Methode ist, die nicht selbst getestet werden kann, würde ich Ansatz 2 verwenden, um sicherzustellen, dass beim Aufruf von postLogin die gewünschte Funktionalität von getShoppingCart wie erwartet ausgeführt wird.

Nastya S
quelle
1

Beim Testen eines Funktionsaufrufs (ungültig oder nicht), der eine Nebenwirkung hat, ist es am vollständigsten zu testen, ob die Nebenwirkung nicht nur auftritt, sondern ob die Nebenwirkung (Systemausgabe oder oder Zustandsänderung) die gewünschte ist.

hotpaw2
quelle
1
Obwohl dies zutrifft, sollten Sie auch bedenken, dass die Details der auftretenden Nebenwirkungen Teil des internen Zustands eines anderen Moduls sein können. Wenn Sie diese Details überprüfen, koppeln Sie Ihren Test nicht nur mit dem betreffenden Modul Es wird aber auch das andere Modul getestet, was zu spröden Tests führen könnte, wenn sich diese Details wahrscheinlich ändern. Das Verspotten der Schnittstelle zwischen Modulen beugt diesem Problem vor.
Jules
0

Ich werde nicht auf Ihr Design eingehen, aber in Ihrem Fall würde ich den ersten Ansatz wählen, da mit Unit-Tests getestet werden soll, welche Methoden unabhängig von ihrer Arbeit in der Domäne technisch postLoginfunktionieren. Technisch heißt es, getShoppingCarddass man testen muss, was wirklich anruft getShoppingCard. Ich würde auch einen weiteren Test erstellen, um getShoppingCardzu testen, was er tut, und wenn er Nebenwirkungen hat, werde ich ihn in diesem neuen Test überprüfen.

La VloZ Merrill
quelle
0

Du hast einen Fehler in postLogin. Als erstes sollten Sie einen Unit-Test erstellen, der beim Aufruf von postLogin ohne die erwarteten Informationen "fehlschlägt".

Ausgehend von der obigen Idee besteht eine andere Alternative aus den 2 vorgeschlagenen darin, die Informationen über den Einkaufswagen als Parameter einzufügen. Wenn Sie nicht über die richtigen Informationen verfügen, lösen Sie eine ungeprüfte Ausnahme aus. Dies wird deutlich machen, dass Ihre Methode ohne die richtigen Details zum Scheitern verurteilt ist.

Dies erfordert eine kleine Änderung, bei der der Client, der gerade das PostLogin anruft, auch die Warenkorbinformationen weitergeben muss. Für mich ist dies immer noch schlüssig, da Sie sehen, dass sie gekoppelt sind. Diese Kopplung erfolgt durch den Anrufer.

Dann müssten Sie getShoppingCart nicht einmal in postLogin testen, da die zu testende Methode postLogin ist. Es ist das, das den Fehler hat und das einzige, das eine ordnungsgemäße Korrektur und Überprüfung erfordert. Mit der injizierten Abhängigkeit können Sie sie problemlos unter anderen Bedingungen testen und sicherstellen, dass kein Fehler ausgegeben wird.

Gummi
quelle