2009-05-05 2 views
8

Ich habe eine Klasse Ich bin Unit-Tests, die relativ umfangreiche Datenbank-Setup erfordert, bevor die einzelnen Testmethoden ausgeführt werden können. Dieses Setup benötigt eine lange Zeit: Aus Gründen, die hoffentlich für die vorliegende Frage nicht relevant sind, muss ich die DB programmatisch statt aus einem SQL-Dump auffüllen.Setup und Abbau komplexer Datenbankstatus mit Hibernate/Spring/JUnit

Das Problem, das ich habe, ist mit dem Abbau. Wie kann ich alle Änderungen in der db-Setup-Phase einfach rückgängig machen?

Ich verwende derzeit Hibernate + Spring Transactional Testing, so dass meine individuellen Testmethoden in Transaktionen eingebettet sind.

Eine Lösung wäre, das db Setup innerhalb jeder Testmethode zu machen, so dass das db Setup automatisch zurückgesetzt wird. Die Testmethoden würden jedoch ewig dauern, da für jede Methode die Datenbank erneut vorbereitet werden muss.

Irgendwelche anderen Ideen? Im Grunde bin ich auf der Suche nach einem Weg, um meine db-Setup zu starten, führen Sie meine einzelnen Tests (jeweils in eine Transaktion verpackt, die nach der Ausführung zurückgesetzt wird), und dann Rollback der ursprünglichen db-Setup. Irgendwelche Ideen, um das in einer Hibernate/Spring/Junit Mode zu machen? Gibt es einen Hibernate-Befehl "Alle Tabellen löschen"?

Antwort

7

Sind Sie mit einem bestimmten Datenbankanbieter festgefahren? Wenn nicht, könnten Sie eine In-Memory-Datenbank verwenden, z. B. HSQLDB. Wenn Sie mit den Tests fertig sind, werfen Sie einfach den Zustand weg. Dies ist nur sinnvoll, wenn die Tabellen zu Beginn der Testsuite leer sein können (also vor dem programmatischen Setup).

Sie müssen noch Tabellen erstellen, aber wenn alles über Hibernate korrekt zugeordnet wurde, können Sie die Tabelle mit den Tabellen hbm2ddl generieren.Alles, was Sie tun müssen, ist Folgendes zu Ihrer Test Sitzung Fabrik Definition hinzufügen:

<session-factory> 
    ... 
    <property name="hibernate.hbm2ddl.auto">create</property> 
    ... 
</session-factory> 

Wenn diese Lösung, die ich auf sie anwendbar scheint erarbeiten können.

+0

Manchmal vergesse ich die einfachsten Optionen. Bonuspunkte für Sie. –

+0

Also, wenn Sie dies als Lösung akzeptieren, bedeutet das, dass Sie sich für das db setup/tear down pro Einzeltest entschieden haben? –

+0

Ich ging tatsächlich mit der Einrichtung der Datenbank einmal für eine Reihe von Tests in der gleichen Klasse mit einer statischen @ BeforeClass Junit-Methode definiert. Aber es wäre einfach genug, auf Testbasis mit einer @Before-JUnit-Methode zu arbeiten. –

0

DNUnit sollten Sie in dieser Hinsicht helfen. Sie können für jeden einzelnen Testfall separate Datensätze erstellen, wenn Sie dies wünschen.

0

DBUnit wird viel dabei helfen. Sie könnten Autocommits auf JDBC theoretisch deaktivieren, aber es wird haarig. Die naheliegendste Lösung ist, DBUnit zu verwenden, um Ihre Daten in einem bekannten Status festzulegen, bevor Sie die Tests ausführen. Wenn Sie aus irgendeinem Grund Ihre Daten nach dem Ausführen der Tests wieder benötigen, können Sie @AfterClass in einer Suite anzeigen, die alle Ihre Tests ausführt. Es wird jedoch allgemein als eine bessere Vorgehensweise angesehen, Ihre Tests einzurichten und dann auszuführen Wenn der Test fehlschlägt, liegt es nicht nur daran, dass es keine Prestine-Umgebung aufgrund eines Fehlers beim Bereinigen eines anderen Tests gab. Sie stellen sicher, dass jeder Test seine Umgebung direkt einrichtet.

+0

würde nicht mit DBUnit zu SQL Scripting konzeptionell gleichwertig sein, die in der Frage ausgeschlossen wurde? – topchef

+0

Ich habe es nicht speziell in der Frage erwähnt, aber ich bin vertraut mit DBUnit und ich habe es vermieden, weil ich nicht eine Tonne DBUnit Test Fixtures pflegen wollte, wenn es einfacher war, die DB programmatisch zu erzeugen. Allerdings kann ich bei der Kugel eine bessere Lösung verpassen. –

0

Eine Lösung, die Sie in Betracht ziehen sollten, ist eine "manuelle" Rollback- oder Kompensationstransaktion in db-Zerlegung zu verwenden. Ich nehme an (und wenn es nicht so ist, sollte es ein triviales Add-on zu Ihren Hibernate-Entitäten sein), haben alle Ihre Entitäten das Attribut datetime create, das angibt, wann sie in die Tabelle eingefügt wurden. Ihre Db-Setup-Methode sollte Zeit vor allem anderen aufnehmen. Dann haben Sie eine ziemlich einfache Prozedur für den DB-Abbau, um alle Entitäten zu löschen, die nach der Zeit erstellt wurden, die in db setup aufgezeichnet wurde.

Natürlich funktioniert dies nicht für Updates in db-Setup ... Aber wenn Sie eine begrenzte Anzahl von Updates haben, dann in Betracht ziehen, unberührten Bild für diese Art von Daten zu speichern und wiederherstellen es während db Abbau.

0

Wenn Sie mit einer relativ kleinen Datenbank und mit einem DBMS arbeiten, das Backups/Exporte relativ schnell durchführen kann (wie MS SQL Server), können Sie vor den Tests eine Datenbanksicherung erstellen und diese dann wiederherstellen wenn alle Tests abgeschlossen sind. Auf diese Weise können Sie eine Entwicklungs-/Testdatenbank einrichten und sie als Startzustand für alle Ihre Tests verwenden.

Ich habe es mit nativen JDBC, Ausführen von '' Backup-Datenbank '' und '' Datenbank wiederherstellen '' T-SQL-zwischen-Tests, und es funktionierte einigermaßen gut.

Dieser Ansatz hängt jedoch davon ab, dass der DBMS-Server auf Ihrem lokalen Computer (für angemessene Geschwindigkeit), ausreichende Berechtigungen (was kein Problem sein sollte) und die Gesamtgröße der Datenbank nicht mehr als ein paar Zehn auf MB - zumindest nach meiner Erfahrung.

0

Gibt es einen Grund, dass Sie eine Verbindung zur Datenbank haben müssen, um Ihre Komponententests auszuführen? Es scheint, dass es einfacher ist, die Klasse zu refaktorieren, um die Interaktion mit der Datenbank zu verspotten. Sie können Klassen (mit einigen Ausnahmen) sowie Schnittstellen mit EasyMock (www.easymock.org) vortäuschen.

Wenn Ihre Klasse auf einen komplexen, bereits vorhandenen Zustand in einer verbundenen Datenbank angewiesen ist, wäre es wahrscheinlich einfacher, schnellere Tests mit Mocks zu schreiben. Wir wissen nicht, wie groß Ihr Projekt ist oder wie oft Ihre Tests ausgeführt werden, aber die Ausführungszeit kann etwas Besonderes sein, besonders in einem großen Projekt.

0

Hibernate hat ein nettes kleines Feature, das stark unter dokumentiert und unbekannt ist. Sie können ein SQL-Skript während der Erstellung der SessionFactory direkt nach der Generierung des Datenbankschemas ausführen, um Daten in einer neuen Datenbank zu importieren. Sie müssen nur eine Datei namens import.sql in Ihrem Klassenpfadstamm hinzufügen und entweder create oder create-drop als Ihre Eigenschaft hibernate.hbm2ddl.auto festlegen.

http://in.relation.to/Bloggers/RotterdamJBugAndHibernatesImportsql

Verwandte Themen