2012-04-12 3 views
30

Wie verhöhnt man die vielen Abhängigkeiten, die für Integrationstests benötigt werden?Mocking für Integrationstests

Ich verwende Mockito für meine 'reinen' Unit Tests. "Rein" bedeutet in diesem Fall, dass eine einzelne Klasse getestet wird und alle Abhängigkeiten gespottet werden. Schön.

Jetzt kommen Integrationstests. Lassen Sie uns sagen, in diesem Fall ein Integrationstest so etwas wie dies testen:

  1. Nachricht in eine Warteschlange gestellt wird
  2. Nachricht ‚verarbeitet‘ wird
  3. Antwortnachricht auf einer Antwortwarteschlange setzen

Lassen Sie uns auch sagen, dass die Verarbeitung, die in Schritt 2 passiert, ernsthafte Zeug ist. Es stützt sich auf viele Datenbankinteraktionen, auf mehrere externe Dienste, das Dateisystem, alle möglichen Dinge. Es gibt auch viele Nebenwirkungen, die der Fluss auslösen wird, so dass ich nicht einfach sicherstellen kann, dass die Antwort richtig ist - ich muss die Nebenwirkungen überprüfen.

Jede dieser Abhängigkeiten wird von einer einzigen zustandslosen Serviceklasse umschlossen, die sie schön und ansprechend macht.

Wie gehen Leute damit um?

Ich würde gerne Mockito verwenden, so dass ich die Nebenwirkungen, die der obige Fluss haben wird, überprüfen konnte. Mocktios Dokumentation (und zu einem großen Teil ihre Implementierung) scheint jedoch stark dagegen zu kämpfen, sie in anderen Zusammenhängen als "reinen" Komponententests zu verwenden. Ich habe versucht, diesen Weg zu gehen, aber

  • Es ist schwierig, die Stub-Daten zu füllen (wie es viele, es ist)
  • Es ist schwer zu haben Frühling jene stubbed Instanzen in meine Bohnen injiziert
  • Es ist schwierig, um die Mocks "zurückzusetzen", so dass ich eine andere Menge von Interaktionen verifizieren kann, ohne die Stubs zu löschen.

EDIT

Ich weiß, dass ich die Datenbank Problem mit so etwas wie eine HSQLDB Instanz umgehen konnte, aber es ist immer noch die Frage der externen Dienstleistungen. Für die Wiederholbarkeit kann ich mich nicht darauf verlassen, dass diese Dienste in Betrieb sind, in dem Zustand sind, den ich benötige, usw. Die einzige Option, die ich dort sehe, ist, sie zu verspotten.

Whatdaya tun?

+1

Nur um zu klären, wie Integrationstests auf zwei Arten vorgenommen werden können. Es klingt, als ob Sie Integrationstests wie im Test meinen, dass verbindungsfähige Komponenten gut zusammenarbeiten (im Wesentlichen das Testen der APIs). Aber manchmal bezieht sich die Integration auf Ende-zu-Ende, so dass Sie Ihren Dienst nicht verspotten und tatsächlich zulassen, dass er die Datenbank trifft. Diese Klarstellung kann bei der Antwort helfen. Bitte beachten Sie http://stackoverflow.com/questions/4904096/whats-the-difference-between-unit-functional-acceptance-and-integration-test zur weiteren Erläuterung der Typen –

+0

gilt für jeden Test (Integration oder Ende-zu-Ende), der viele externe Abhängigkeiten erfordert. Zum Beispiel könnte ich meine Datenbank-Stubs durch eine HSQLDB-Instanz ersetzen, aber ich habe immer noch alle anderen Dienste. Will die Frage ein wenig redigieren, um zu klären. –

+0

Also, wie hast du das Spottproblem schließlich gelöst? – Pupsik

Antwort

7

Große Frage.

Es scheint, als ob Sie die Grenzen von Mockito erreicht haben. Mockito ist großartig, wenn Sie Objektinteraktionen untersuchen möchten.

Was Sie jedoch wollen, scheint Beobachtbarkeit (und Kontrollierbarkeit) auf einer höheren Abstraktionsebene zu sein. Ich habe Angst, dass die Mocks oder Stummel, die Sie dafür brauchen, sorgfältig entworfen und handgefertigt werden sollten.

Auf der Ebene der Einheit können diese Mocks mit Mockito erzeugt werden. Auf der Integrationsebene wird dies viel schwieriger, und Sie werden zweckmäßige Testbarkeitsschnittstellen benötigen.

+1

Ja, es klingt wie auf der Integrationsebene Leute "machen das Beste daraus", entweder indem sie tun, was sie können, indem sie Bibliotheken verspotten oder indem sie tatsächlich Testinstanzen von Diensten/Datenbanken treffen.Ich arbeite gerade an einer Groovy-basierten Mockito-Erweiterung, um die Integrationstests ein bisschen weniger schmerzhaft zu machen. –

7

Um Dinge wie Datenbanken, Webdienste, das Dateisystem und so weiter zu verspotten, werden Sie wahrscheinlich ein wenig umgestalten wollen. Für jeden externen Dienst sollten Sie eine Wrapper-Klasse schreiben, die eine Methode für jede Operation enthält, die Sie ausführen möchten. Jede dieser Methoden sollte keine tatsächliche Logik haben, sondern nur ihre Parameter in der Art und Weise durchgehen, wie der externe Dienst sie versteht, und ein Objekt zurückgeben, das alle Daten enthält, die der externe Dienst zurückgibt. Wenn Sie beispielsweise mit einer Datenbank interagieren, formatiert die Wrapperklasse ihre Parameter möglicherweise in eine SQL-Anweisung, übergibt sie an ein vorhandenes Objekt Connection und gibt für das Ergebnis eine List zurück.

Da die Methoden der Wrapper-Klasse keine Logik enthalten (dh keine if/else, keine Schleifen und keine Ausnahmebehandlung); Es ist nicht erforderlich, die Wrapperklasse im Unit-Test zu testen.Sie sollten die Wrapper-Klasse testen, um sicherzustellen, dass ihre Verantwortlichkeiten korrekt ausgeführt werden (dh, die SQL-Anweisung hat z. B. die gewünschten Auswirkungen auf die Datenbank).

Schreiben Sie nun die Klassen neu, die mit den externen Services interagieren, sodass sie stattdessen mit den Wrapper-Klassen interagieren. Es ist dann einfach, Unit-Tests zu testen - Sie müssen nur die Wrapperklassen nachahmen.

+0

Danke David. Meine externen Dienste sind ziemlich gut abstrahiert - jeder ist mit einer einzelnen Spring-Singleton-Serviceklasse verpackt. Sogar für ein kompliziertes Szenario wird das Spotten schwierig. Es gibt eine Menge Daten, die stubbed sein müssen, oft wird die gleiche Service-Methode mehrmals aufgerufen, was bedeutet, dass ich die Stubs mehrere Werte zurückgeben muss, dann gibt es das Problem, die mit Spring injiziert bekommen .. wird haarig. Ich muss davon ausgehen, dass die Leute das auf eine sauberere Weise gelöst haben –

+0

Müssen sie mit einem Singleton gewickelt werden? Singletons sind notorisch schwer zu verspotten. Können Sie Dinge so konstruieren, dass der Wrapper kein Singleton ist? –

+0

Ich würde auch fragen, warum die gleiche Service-Methode innerhalb eines Tests oft aufgerufen wird. Vielleicht sind deine Testmethoden zu groß? Ich glaube fest an die Regel "Eine Aussage pro Testmethode"; es macht wirklich viel sauberere Tests. –

0

Wenn es ein http oder Rest-Mock-Framework gibt, sollte das gut sein.

Alle komplizierten Abhängigkeiten können aufgezeichnet, geändert und wiedergegeben werden.