2008-11-11 17 views
35

Ich arbeite an einem Spring MVC-Projekt, und ich habe Komponententests für alle verschiedenen Komponenten im Quellbaum.Komponententests vs. Integrationstests mit Spring

Zum Beispiel, wenn ich einen Controller HomeController, haben die ein LoginService hinein injiziert haben muss, dann in meiner Unit-Test HomeControllerTest ich instanziiert das Objekt einfach als normal (außerhalb des Frühlings) und injizieren die Eigenschaft:

protected void setUp() throws Exception { 
    super.setUp(); 
    //... 
    controller = new HomeController(); 
    controller.setLoginService(new SimpleLoginService()); 
    //... 
} 

Das funktioniert gut zum Testen jeder Komponente als eine isolierte Einheit - außer jetzt, dass ich ein paar Dutzend Klassen im Projekt habe, nachdem ich eine Klasse geschrieben und einen erfolgreichen Komponententest geschrieben habe, vergesse ich immer meine Spring MVC zu aktualisieren Kontextdatei, die die tatsächliche Verkabelung in der bereitgestellten Anwendung durchführt. Ich stelle fest, dass ich vergessen habe, die Kontextdatei zu aktualisieren, wenn ich das Projekt auf Tomcat ausstelle und eine Reihe von NullPointern aus nicht verkabelten Beans finde.

So, hier sind meine Fragen:

  1. Dies ist mein erster Frühling Projekt - ist es normal, Unit-Tests für die einzelnen Bohnen zu schaffen, wie ich getan habe, und dann eine zweite Reihe von Tests erstellen (Integrationstests) um zu testen, dass alles wie erwartet mit dem tatsächlichen Anwendungskontext funktioniert? Gibt es dafür eine bewährte Methode?

  2. Wie trennen Sie außerdem die Komponententests von den Integrationstests? Ich habe alle Quellcode in src, die Unit-Tests in test - sollte es einen zweiten Test-Ordner (wie test-integration) für die Integration Testfälle?

Da dies mein erstes Frühlings Projekt, ich bin gespannt, wie andere gehen in der Regel über diese Art der Sache zu tun - und nicht neu erfinden das Rad, frage ich lieber den Rest der Gemeinschaft.

Antwort

32

Ich kann nicht sagen, eine Best Practice zu sein, aber hier ist, was ich in der Vergangenheit getan habe.

Unit-Tests:

  • Unit-Tests erstellen für nicht-triviale Bohnen (dh die meisten Ihrer Frühling im Zusammenhang Bohnen)
  • Verwendung Mocks für injizierte Dienste, bei denen praktisch (dh die meisten wenn nicht alle die Zeit).
  • Verwenden Sie eine Standardbenennungskonvention für diese Tests im Projektverzeichnis test. Die Verwendung von Test oder TestCase als Präfix oder Suffix für den Klassennamen scheint weit verbreitet zu sein.

Integrationstests:

  • ein AbstractIntegrationTestCase erstellen, die ein SpringWebApplicationContext für den Einsatz in intetgration Test clases einrichtet.
  • Verwenden Sie eine Namenskonvention für Integrationstests im Verzeichnis test. Ich habe IntTest oder IntegrationTest als Präfix oder Suffix für diese Tests verwendet.

einrichten drei Ant test Ziele:

  1. Test alle (oder was auch immer Sie es nennen wollen): Laufeinheit und Integrationstests
  2. Test: Tests Run Unit (nur weil test scheint die häufigste Verwendung für Unit-Tests
  3. Test-Integration zu sein. die Integrationstests laufen

Wie bereits erwähnt, Sie können die Namenskonventionen verwenden, die für Ihr Projekt sinnvoll sind.

Was das Trennen der Einheit von Integrationstests in ein separates Verzeichnis betrifft, so glaube ich nicht, dass es wichtig ist, solange die Entwickler und ihre Werkzeuge sie leicht finden und ausführen können.

Als Beispiel verwendete das letzte Java-Projekt, an dem ich mit Spring arbeitete, genau das, was oben beschrieben wurde, wobei Integrationstests und Komponententests im selben Verzeichnis wie test lebten. Grails-Projekte hingegen trennen Unit- und Integrationstest-Verzeichnisse explizit unter einem allgemeinen Testverzeichnis.

+1

Das klingt nach einer guten Strategie. Aber mit den Komponententests und Integrationstests in den gleichen Verzeichnissen gibt es für Eclipse keine Möglichkeit, sie voneinander zu unterscheiden, oder? Die einzigen Optionen von Eclipse zum Ausführen von Junit-Tests sind, nur einen auszuführen oder alle in einem bestimmten Ordner auszuführen - sie können nicht nach Namen wie Ant aufgeteilt werden. –

+0

Ich musste zurückgehen und Eclipse überprüfen - Sie haben Recht, ich sehe keine Möglichkeit, die Tests zu unterscheiden, wenn sie sich im selben Verzeichnis befinden. Mein letztes Frühjahrsprojekt wurde in Idea/Intellij gemacht und es war lange genug, dass ich mich nicht mehr genau an die IDE-Konfiguration erinnere. –

4

Viele der langweiligen Doppelbuchhaltung mit Frühling geht weg, wenn Sie auch zu einem rein annotierten Regime wechseln, wo Sie alle Ihre Beans mit @Component, @Controller, @Service und @Repository kommentieren. Fügen Sie einfach @Autowired zu den Attributen hinzu, die Sie injizieren müssen.

Siehe Abschnitt 3.11 der Feder-Referenzanleitung. http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config

In einem verwandten Hinweis haben wir die Division Unit/Integratrion Tests verwendet, die KenG beschreiben. In meinem letzten Regime haben wir auch eine dritte "Klasse" von Tests eingeführt, "ComponentTests". Diese laufen mit voller Federverdrahtung, aber mit verkabelten Stub-Implementierungen (mit Komponenten-Scan-Filtern und Anmerkungen im Frühjahr).

Der Grund, warum wir das getan haben, ist, dass Sie für einige der "Service" -Layer eine horrende Menge an handcodierter Verdrahtungslogik haben, um die Bean manuell zu verkabeln, und manchmal lächerliche Mengen von Mock-Objekten. 100 Leitungen für 5 Testlinien sind nicht ungewöhnlich. Die Komponententests mildern dieses Problem.

+0

Leider verwende ich immer noch Java 1.4 :( –

0

Wenn ich Integrationstests für Webanwendungen erstellt habe, habe ich sie in einem separaten Verzeichnis abgelegt. Sie werden mithilfe von jUnit oder TestNG erstellt und interagieren mit dem zu testenden System. Dabei wird etwa Selenium verwendet, die auf die Webseiten trifft, als wären sie Benutzer. Der Zyklus würde folgendermaßen aussehen: kompilieren, Komponententests ausführen, die Webanwendung erstellen, auf einem laufenden Server bereitstellen, die Tests ausführen, die Bereitstellung deimplementieren und Ergebnisse melden. Die Idee ist, das ganze System zu testen.

2

Verwenden Sie die InitializingBean-Schnittstelle (implementiert eine Methode "afterPropertiesSet") oder geben Sie eine Init-Methode für Ihre Beans an. InitializingBean ist in der Regel einfacher, weil Sie nicht daran denken müssen, die Init-Methode zu Ihren Beans hinzuzufügen.

Verwenden Sie afterPropertiesSet, um sicherzustellen, dass alles als nicht null injiziert wird. Wenn es null ist, wird eine Ausnahme ausgelöst.

0

In Bezug auf Laufeinheitstests getrennt von Integrationstests, lege ich all diese in ein Integrationstestverzeichnis und führe sie unter Verwendung von IDE/Ant unter Verwendung eines Ansatzes wie this. Funktioniert bei mir.

6

Einige isolierten Punkte:

Ja, es ist ein gemeinsames Konzept Tests zum Frühling - separaten Unit-Tests und Integrationstests, wo die ehemaligen Kontext keine Feder nicht geladen.

Für Ihre Komponententests sollten Sie sich vielleicht überlegen, ob Sie Ihre Tests auf ein isoliertes Modul konzentrieren.

Wenn Sie Tests sind in einer Tonne von Abhängigkeiten Verdrahtung dann sind sie nicht wirklich Komponententests. Es handelt sich um Integrationstests, bei denen Abhängigkeiten mit Hilfe von neuen anstelle von Abhängigkeitsinjektionen verknüpft werden. Zeitverschwendung und doppelter Aufwand, wenn Ihre Produktionsanwendung Spring verwendet!

Einfache Integrationstests zum Aufrufen der Spring-Kontexte sind hilfreich.

Die @required-Annotation kann Ihnen dabei helfen, sicherzustellen, dass Sie die erforderlichen Abhängigkeiten in Ihrer Spring-Verdrahtung finden.

Vielleicht in Maven schauen, die Ihnen explizite Phasen gibt, um Ihre Einheit und Integration Tests an zu binden. Maven ist in der Spring Community ziemlich weit verbreitet.

0

Der Unterschied zwischen Komponententest und Integrationstest ist, Komponententest lädt nicht unbedingt Ihren Kontext, Sie konzentrieren sich auf den Code, den Sie geschrieben haben - es funktioniert schnell, das ist mit und ohne Ausnahmen, durch Verspottung ruft hinein. Bei Integrationstests laden Sie jedoch den Kontext und führen Ende-zu-Ende-Tests wie tatsächliche Szenarien durch.