Lohnt es sich tatsächlich, einen API-Client zu testen?

38

Das ist etwas, das mich jetzt schon eine Weile beunruhigt. Lohnt es sich tatsächlich, einen API-Client zu testen?

Angenommen, Sie erstellen eine kleine Klasse, um die Aufrufe einer petshop-REST-API zu abstrahieren. Der Petshop ist eine sehr einfache API und verfügt über eine Reihe grundlegender Methoden:

  • listProducts()
  • getProductDetails(ProductID)
  • addProduct(...)
  • removeProduct(ProductID)

Um dies zu testen, müssten wir entweder einen Mock-Service erstellen oder die Antworten verspotten. Aber das scheint übertrieben; Ich verstehe, dass wir sicherstellen möchten, dass unsere Methoden nicht aufhören, Tipp- / Syntaxfehler zu verarbeiten, aber da wir Funktionen schreiben, die Remotemethoden aufrufen, und dann von diesen Remotemethoden gefälschte Antworten erstellen, scheint es so eine Verschwendung von Mühe und dass wir etwas testen, das nicht wirklich scheitern kann. Schlimmer noch, wenn sich die Remote-Methode ändert, bestehen unsere Komponententests, während die Produktion nicht funktioniert.

Ich bin mir ziemlich sicher, dass mir etwas fehlt, oder ich habe das falsche Ende des Stocks oder ich sehe den Wald vor lauter Bäumen nicht. Kann mich jemand auf den richtigen Weg bringen?

Phillip B. Oldham
quelle
1
Wenn dies nicht eine so einfache API mit grundlegenden Methoden wäre, würden Sie sich anders fühlen? Auch ein Schuppen muss dem Schnee standhalten.
JeffO

Antworten:

31

Die Aufgabe eines Remote-API-Clients besteht darin, bestimmte Aufrufe auszulösen - nicht mehr und nicht weniger. Daher sollte sein Test sicherstellen, dass er diese Anrufe ausgibt - nicht mehr und nicht weniger.

Sicher, wenn der API-Anbieter die Semantik seiner Antworten ändert, fällt Ihr System in der Produktion aus. Aber das ist nicht die Schuld Ihrer Kundenklasse. Es ist etwas, das nur in Integrationstests gefangen werden kann. Indem Sie sich auf Code verlassen, der nicht unter Ihrer Kontrolle steht, haben Sie die Möglichkeit aufgegeben, die Richtigkeit durch interne Tests zu überprüfen - es war ein Kompromiss, und das ist der Preis.

Das Testen einer Klasse, die nur aus Delegierungen an eine andere Klasse besteht, kann jedoch eine niedrige Priorität haben, da das Risiko komplexer Fehler vergleichsweise gering ist. Das gilt jedoch für jede Klasse, die nur aus einheitlichen Einzeilern besteht. Es hat nichts damit zu tun, den Code eines anderen Anbieters aufzurufen.

Kilian Foth
quelle
Ich bin mir nicht sicher, ob ich damit einverstanden bin. Sie können testen, was foo()vorher aufgerufen wurde bar(), aber das bedeutet nicht, dass das Anrufen foo()vorher bar()richtig ist. Ein solcher Komponententest würde auch dann bestehen, wenn der Code falsch ist. Und wenn das alles ist, was der Client tut, ist es relativ mühsam , die Mocks einzurichten, die prüfen, ob foo()er zuvor aufgerufen wurde. bar()Dies lässt sich mit einem flüchtigen Blick auf den Clientcode überprüfen.
Doval
1
Sie können testen, ob eine add()Methode zwei Zahlen korrekt addiert. Dies bedeutet jedoch nicht, dass das Addieren an dieser Stelle des Algorithmus das Richtige ist. Der Komponententest add()wäre erfolgreich, obwohl Ihr Programm falsch ist. Wenn es ist die falsche Sache, dann ist Ihr levenshteinDistance()Verfahren ist schuld, nicht das add()Verfahren. Das ist genau das gleiche. Bei der Aufteilung von Code in Methoden muss sich jede Methode nur darum kümmern, dass eine Sache korrekt ist.
Kilian Foth
3
Jetzt sehe ich, wo wir nicht übereinstimmen! Wenn Sie verlassen sich auf einem externen Zoohandlung, mir das bedeutet , dass Ihr System Enden an der HTTP - Grenze, damit die ausgegebenen REST Anrufe sind Ausgänge und vorbehaltlich der Prüfung. Wenn Sie die Zoohandlung als Teil dieses Moduls betrachten, ist das Muster der ausgegebenen Anrufe ein Implementierungsdetail, und bei einem Komponententest gibt es keine Geschäftsvorschrift dafür.
Kilian Foth
2
"Daher sollte sein Test bestätigen, dass er diese Aufrufe ausgibt." Ich denke, das ist die Perspektive, die ich nicht gesehen habe. Vielen Dank!
Phillip B Oldham
1
So könnte mein Unit-Test beispielsweise überprüfen, ob bei bestimmten Parametern der Hauptteil der auszuführenden Anforderung der richtige ist.
Maria Ines Parnisari
9

Kurze Antwort:

Alle Methoden sollten einheitlich getestet werden.

Lange Antwort:

Ja. Es lohnt sich.

Dies sind einige Dinge, die Unit-Tests für API-Aufrufmethoden testen sollten:

  • Dass Sie wohlgeformte oder korrekte Parameter an die API-Aufrufe übergeben.
  • Dass Sie entsprechend auf bestimmte Arten von Daten reagieren, die von den APIs zurückgegeben werden (verspottet oder nicht). Wenn die API beispielsweise eine leere Zeichenfolge zurückgibt, sollte Ihre Methode einen Standardwert zurückgeben (nur ein Beispiel).
  • Das Verhalten der Aufrufermethoden bei API-Aufrufen führt zu einem Fehler

Dies sind Dinge, die die aufgerufene Methode tun kann, um den API-Dienst zu verspotten, und die durch gründliches Testen sicherstellen, dass Fehler nicht durch einen Fehler im Client-Code verursacht werden, der die API aufruft.

Tulains Córdova
quelle
Sie sagen "verspottet oder nicht" ... ist es in Ordnung, gegen die echte API zu testen? Kann ich es einen Integrationstest nennen, obwohl es aussieht wie ein Unit-Test? Oder gibt es noch etwas, das man so nennen kann? Ich würde gerne testen, ob mein API-Wrapper das tut, was er
Dan Rosenstark
1
@DanRosenstark Ich denke, wenn der API-Service nicht verspottet wird, handelt es sich um einen Integrationstest.
Tulains Córdova
Würden Sie nicht in 5 Sekunden wissen, ob Sie die Daten korrekt zurückerhalten, wenn Sie die API tatsächlich aufrufen? Da es sich bei den API-Mocks nicht um echte Aufrufe handelt, würden sie nur fehlschlagen, wenn sie die API ändern. In diesem Fall würden Ihre Mock-Tests bestanden, aber die echten Aufrufe würden fehlschlagen. Scheint sinnlos
MattE
5

Dies wären keine Komponententests, da Sie die Ein- und Ausgabe Ihres Systems testen, eher wie eingeschränkte Integrationstests.

Seien Sie sehr vorsichtig , wenn Sie sagen , „es wie eine Verschwendung von Aufwand scheint und dass wir etwas zu test , die nicht wirklich scheitern kann“ - es fehlschlagen kann, wird es scheitern, wird es wahrscheinlich in einer Weise scheitern , dass man nicht voraussehen kann, die Fehler werden schlimmer, wenn keine Tests vorhanden sind.

Der Fehler, den Sie hier machen, hängt mit der Erfindung von Rädern zusammen: Das Aufrufen von Remotediensten und APIs ist ein sehr verbreitetes Szenario. Daher gibt es einige ziemlich gute Tools, mit denen Sie dies testen können. Als ich das letzte Mal an einer Anwendung arbeitete, die eine Verbindung zu Remotediensten herstellte, verwendete ich SoapUIDies könnte einen Dienst anzeigen und entweder Scheinaufrufe an diesen Dienst tätigen oder sich als lokale Kopie des Servers verhalten, auf dem Sie Testanrufe tätigen und die Anforderungen und Antworten nachverfolgen können. Das Einrichten dauerte Minuten und war ebenfalls sehr schnell zu aktualisieren, wenn sich die Remote-Schnittstelle änderte. Ich habe es in einem REST-Szenario nicht verwendet, aber selbst wenn es dafür nicht gut funktioniert (oder wenn es in Zukunft bessere Tools gibt, liest möglicherweise jemand diese Antwort), sollten Sie in der Lage sein, ein Tool zu finden, das sich nachahmen lässt Ein Service für Sie und wenn es Zeit ist, Ihren Code bereitzustellen, werden Sie froh sein, dass Sie es getan haben.

Glenatron
quelle