2009-05-05 15 views
8

Ho una classe Sono un test di unità che richiede un'impostazione di database piuttosto estesa prima che i singoli metodi di test possano essere eseguiti. Questa configurazione richiede molto tempo: per ragioni che spero non siano rilevanti per la domanda in questione, ho bisogno di compilare il DB in modo programmatico anziché da un dump SQL.Installazione e demolizione dello stato di un database complesso con Hibernate/Spring/JUnit

Il problema che ho è con il tear-down. Come posso facilmente ripristinare tutte le modifiche apportate nella fase di configurazione di db?

Attualmente sto utilizzando il supporto per il test transazionale Hibernate + Spring, in modo tale che i miei singoli metodi di test siano integrati nelle transazioni.

Una soluzione sarebbe quella di eseguire l'installazione del db all'interno di ciascun metodo di test, in modo tale che l'impostazione del db venga ripristinata automaticamente. Tuttavia, i metodi di test impiegherebbero un'eternità per essere eseguito poiché ogni metodo avrebbe bisogno di ri-preparare il database.

Altre idee? Fondamentalmente, sto cercando un modo per eseguire il mio db setup, eseguire i miei test individuali (ciascuno avvolto in una transazione che viene sottoposta a rollback dopo l'esecuzione) e quindi eseguire il rollback del setup iniziale di db. Qualche idea su come farlo funzionare in una moda Hibernate/Spring/Junit? Esiste un comando equivalente "rilascia tutte le tabelle" di Hibernate?

risposta

7

Sei bloccato con un fornitore di database specifico? In caso contrario, è possibile utilizzare un database in memoria, ad esempio HSQLDB. Quando hai finito con i test, butti via lo stato. Questo è appropriato solo se le tabelle possono essere vuote all'inizio della suite di test (prima della configurazione programmatica, cioè).

È ancora necessario creare tabelle, ma se tutto è mappato in modo ordinato utilizzando Hibernate, è possibile utilizzare hbm2ddl per generare le tabelle.Tutto quello che dovete fare è aggiungere quanto segue al prova definizione fabbrica sessione:

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

Se questa soluzione sembra applicabile posso elaborare su di esso.

+0

A volte mi dimentico delle opzioni più semplici. Punti bonus per te. –

+0

Quindi accettando questo come soluzione significa che hai optato per il db setup/tear down per ogni test? –

+0

In realtà sono andato con l'impostazione del db una volta per una serie di test definiti nella stessa classe utilizzando un metodo @BeforeClass Junit statico. Ma sarebbe abbastanza facile da fare in base al test con un metodo @Before JUnit. –

0

DNUnit dovrebbe aiutare in questo senso. Se lo desideri, puoi creare set di dati separati per ogni singolo caso di test.

0

DBUnit aiuterà molto con questo. In teoria è possibile disattivare l'autocommit su JDBC, ma diventerà peloso. La soluzione più ovvia è utilizzare DBUnit per impostare i dati su uno stato noto prima di eseguire i test. Se per qualche motivo hai bisogno dei tuoi dati dopo aver eseguito i test, puoi guardare @AfterClass su una suite che esegue tutti i test, ma generalmente è considerata una pratica migliore per impostare i test e quindi eseguirli, quindi che se il test fallisce, non è solo perché non ha un ambiente prestino a causa di un errore nel pulire un test diverso. Assicurati che ogni test configuri direttamente il suo ambiente.

+0

non avrebbero utilizzando DBUnit essere concettualmente equivalente a SQL scripting che è stato escluso nella questione? – topchef

+0

Non l'ho menzionato specificamente nella domanda, ma ho familiarità con DBUnit e l'ho evitato perché non volevo mantenere una tonnellata di dispositivi di prova DBUnit quando era più facile generare il DB a livello di programmazione. Tuttavia, potrei mordere il proiettile privo di una soluzione migliore. –

0

Una soluzione da prendere in considerazione è l'utilizzo di un rollback "manuale" o di una transazione di compensazione in formato db. Suppongo (e se non lo è, dovrebbe essere un banale add-on per le tue entità di Hibernate) tutte le tue entità hanno attributi di creazione datetime che indicano quando sono stati INSERITI nella tabella. Il tuo metodo di configurazione db dovrebbe registrare il tempo prima di tutto il resto. Quindi hai una procedura piuttosto semplice per db tear down per eliminare tutte le entità che sono state create dopo il tempo ripetuto in db setup.

Ovviamente, questo non funzionerà per gli aggiornamenti in db setup ... Ma se si dispone di un numero limitato di aggiornamenti, si consiglia di salvare un'immagine pulita per questo tipo di dati e ripristinarla durante l'eliminazione di db.

0

Se si sta lavorando con un database relativamente piccolo e con un DBMS che può eseguire backup/esportazioni relativamente veloci (come MS SQL Server), è possibile considerare la creazione di un backup del database prima dei test e quindi ripristinarlo quando tutti i test sono completi. Ciò consente di impostare un database di sviluppo/test e utilizzarlo come stato iniziale per tutti i test.

L'ho fatto con JDBC nativo, eseguendo test di '' backup database '' e '' ripristino database '' T-SQL, e ha funzionato abbastanza bene.

Tuttavia, questo approccio dipende dall'avere il server DBMS sul computer locale (per una velocità ragionevole), i privilegi sufficienti (che non dovrebbero essere un problema) e la dimensione totale del database non superiore a qualche decina su MB - almeno nella mia esperienza.

0

C'è un motivo per cui è necessario avere una connessione al database per eseguire i test dell'unità? Sembra che potrebbe essere più semplice refactoring della tua classe in modo da poter prendere in giro l'interazione con il database. Puoi prendere in giro le classi (con alcune eccezioni) e le interfacce con EasyMock (www.easymock.org).

Se la classe si basa su uno stato preesistente complesso in un database collegato, sarebbe probabilmente più facile scrivere test di esecuzione più rapidi utilizzando i mock. Non sappiamo quale sia la dimensione del tuo progetto o quanto spesso vengono eseguiti i test, ma il tempo di esecuzione potrebbe essere qualcosa su cui riflettere, soprattutto in un grande progetto.

0

Hibernate ha una piccola funzionalità molto scarsamente documentata e sconosciuta. È possibile eseguire uno script SQL durante la creazione di SessionFactory subito dopo la generazione dello schema del database per importare i dati in un nuovo database. È sufficiente aggiungere un file denominato import.sql nella root del classpath e impostare create o create-drop come proprietà hibernate.hbm2ddl.auto.

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

Problemi correlati