Es gibt zwei Themen, die wir hier betrachten müssen.
Das erste ist, dass Sie alle Ihre Tests aus der Sicht des Komponententests betrachten. Unit-Tests sind äußerst wertvoll, aber nicht die einzigen Arten von Tests. Die Tests können in verschiedene Ebenen unterteilt werden, von sehr schnellen Unit-Tests über weniger schnelle Integrationstests bis hin zu noch langsameren Akzeptanztests . (Es können noch mehr Schichten wie Funktionstests ausgebrochen werden .)
Der zweite Grund ist, dass Sie Aufrufe an Code von Drittanbietern mit Ihrer Geschäftslogik mischen, Testherausforderungen erstellen und möglicherweise den Code spröder machen.
Unit-Tests sollten schnell und häufig durchgeführt werden. Das Verspotten von Abhängigkeiten trägt dazu bei, dass diese Tests weiterhin schnell ausgeführt werden, kann jedoch potenziell zu Lücken in der Abdeckung führen, wenn sich die Abhängigkeit ändert und das Verspotten nicht. Ihr Code könnte beschädigt werden, während Ihre Tests noch grün laufen. Einige spöttische Bibliotheken benachrichtigen Sie, wenn sich die Schnittstelle der Abhängigkeit ändert, andere nicht.
Integrationstests hingegen dienen zum Testen der Interaktionen zwischen Komponenten, einschließlich Bibliotheken von Drittanbietern. Mocks sollten auf dieser Teststufe nicht verwendet werden, da wir sehen möchten, wie das eigentliche Objekt zusammenwirkt. Da wir reale Objekte verwenden, sind diese Tests langsamer und werden nicht annähernd so oft ausgeführt wie unsere Komponententests.
Abnahmeprüfungen werden auf einer noch höheren Ebene durchgeführt, um zu überprüfen, ob die Anforderungen an die Software erfüllt sind. Diese Tests werden für das gesamte System ausgeführt, das bereitgestellt werden würde. Auch hier sollte kein Spott angewendet werden.
Eine Richtlinie, die Menschen in Bezug auf Verspottungen für wertvoll befunden haben, ist, keine Typen zu verspotten, die Sie nicht besitzen . Amazon besitzt die API für S3, damit sie sicherstellen können, dass sie sich nicht darunter ändert. Sie hingegen haben diese Zusicherungen nicht. Wenn Sie die S3-API in Ihren Tests verspotten, kann dies Ihren Code ändern und beschädigen, während alle Tests grün angezeigt werden. Wie können wir Code testen, der Bibliotheken von Drittanbietern verwendet?
Nun, wir tun es nicht. Wenn wir der Richtlinie folgen, können wir keine Objekte verspotten, die wir nicht besitzen. Aber ... wenn wir unsere direkten Abhängigkeiten besitzen, können wir sie verspotten. Aber wie? Wir erstellen einen eigenen Wrapper für die S3-API. Wir können es so gestalten, dass es der S3-API ähnelt, oder wir können es unseren Anforderungen genauer anpassen (bevorzugt). Wir können es sogar etwas abstrakter machen, sagen wir PersistenceService
eher ein als ein AmazonS3Bucket
. PersistenceService
wäre eine Schnittstelle mit Methoden wie #save(Thing)
und #fetch(ThingId)
, die Arten von Methoden, die wir gerne sehen würden (dies sind Beispiele, vielleicht möchten Sie tatsächlich verschiedene Methoden). Wir können jetzt eine PersistenceService
um die S3-API herum implementieren (sagen wir a S3PersistenceService
) und diese außerhalb unseres aufrufenden Codes einkapseln.
Nun zu dem Code, der die S3-API aufruft. Wir müssen diese Aufrufe durch Aufrufe an ein PersistenceService
Objekt ersetzen . Wir verwenden Abhängigkeitsinjektion , um unsere PersistenceService
in das Objekt zu übergeben. Es ist wichtig, nicht nach einem S3PersistenceService
zu fragen, sondern nach einem PersistenceService
. Dies ermöglicht es uns, die Implementierung während unserer Tests auszutauschen.
Der gesamte Code, der zur direkten Verwendung der S3-API verwendet wurde PersistenceService
, verwendet jetzt unser und S3PersistenceService
ruft jetzt alle S3-API-Aufrufe auf. In unseren Tests können wir eine Verspottung durchführen PersistenceService
, da wir sie besitzen, und mithilfe der Verspottung sicherstellen, dass unser Code die richtigen Aufrufe ausführt . Aber jetzt bleibt noch zu testen S3PersistenceService
. Es hat das gleiche Problem wie zuvor: Wir können es nicht testen, ohne den externen Dienst anzurufen. Also ... wir testen es nicht. Wir könnten die S3-API-Abhängigkeiten verspotten, aber dies würde uns wenig bis gar kein zusätzliches Vertrauen geben. Stattdessen müssen wir es auf einer höheren Ebene testen: Integrationstests.
Das mag etwas beunruhigend klingen, wenn man sagt, wir sollten keinen Teil unseres Codes testen, aber schauen wir uns an, was wir erreicht haben. Wir hatten überall eine Menge Code, den wir nicht testen konnten PersistenceService
. Wir haben unser Bibliotheks-Durcheinander von Drittanbietern auf eine einzige Implementierungsklasse beschränkt. Diese Klasse sollte die für die Verwendung der API erforderliche Funktionalität bereitstellen, ist jedoch nicht mit einer externen Geschäftslogik verknüpft. Wenn es einmal geschrieben ist, sollte es daher sehr stabil sein und sich nicht viel ändern. Wir können uns auf langsamere Tests verlassen, die wir nicht so oft ausführen, weil der Code stabil ist.
Der nächste Schritt besteht darin, die Integrationstests für zu schreiben S3PersistenceService
. Diese sollten nach Name oder Ordner getrennt werden, damit wir sie getrennt von unseren schnellen Unit-Tests ausführen können. Integrationstests können häufig dieselben Test-Frameworks wie Unit-Tests verwenden, wenn der Code ausreichend informativ ist, sodass wir kein neues Tool erlernen müssen. Der eigentliche Code für den Integrationstest ist der, den Sie für Option 1 schreiben würden.