2011-12-21 18 views
6

Sto avendo problemi cercando di spingere le modifiche apportate all'interno di una transazione Hibernate al database per DBUnit funzioni correttamente nel mio caso di test. Sembra che DbUnit non stia vedendo le modifiche apportate da Hibernate perché non sono ancora state commesse alla fine della transazione ... e non sono sicuro di come ristrutturare il mio caso di test per farlo funzionare.Ottenere DBUnit al lavoro con Hibernate transazione

Ecco il mio banco di prova troppo semplificata per dimostrare il mio problema: -

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { 
     "classpath:applicationContext-test.xml" 
}) 
@TransactionConfiguration(transactionManager = "transactionManager") 
@Transactional 
public class SomeTest { 
    @Autowired 
    protected DataSource dataSource; 

    @Autowired 
    private SessionFactory sessionFactory; 

    @Test 
    public void testThis() throws Exception { 
     Session session = sessionFactory.getCurrentSession(); 

     assertEquals("initial overlayType count", 4, session.createQuery("from OverlayType").list().size()); 

     //----------- 
     // Imagine this block is an API call, ex: someService.save("AAA"); 
     // But for the sake of simplicity, I do it this way 
     OverlayType overlayType = new OverlayType(); 
     overlayType.setName("AAA"); 
     session.save(overlayType); 
     //----------- 

     // flush has no effect here 
     session.flush(); 

     assertEquals("new overlayType count", 5, session.createQuery("from OverlayType").list().size()); 

     // pull the data from database using dbunit 
     IDatabaseConnection connection = new DatabaseConnection(dataSource.getConnection()); 
     connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory()); 
     QueryDataSet partialDataSet = new QueryDataSet(connection); 
     partialDataSet.addTable("resultSet", "select * from overlayType"); 
     ITable actualTable = partialDataSet.getTable("resultSet"); 

     // FAIL: Actual row count is 4 instead of 5 
     assertEquals("dbunit's overlayType count", 5, actualTable.getRowCount()); 

     DataSourceUtils.releaseConnection(connection.getConnection(), dataSource); 
    } 
} 

La mia idea di utilizzare DBUnit è quello di: -

  • chiamata someService.save(...) che salva i dati in diverse tabelle.
  • Utilizzare DbUnit per ottenere la tabella prevista da XML.
  • Utilizzare DbUnit per ottenere la tabella effettiva dal database.
  • Do Assertion.assertEquals(expectedTable, actualTable);.

Ma, a questo punto, non riesco a ottenere DbUnit per vedere le modifiche apportate da Hibernate all'interno della transazione.

Come devo cambiare per arrivare DBUnit per lavorare bene con Hibernate transazione?

Grazie.

risposta

9

Non ho mai lavorato con DBUnit, ma sembra che TransactionAwareDataSourceProxy farà il trucco. Fondamentalmente è necessario per avvolgere l'origine dati originale con questo proxy e usarlo, invece, in modo che questo codice:

new DatabaseConnection(dataSource.getConnection()) 

passa in realtà attraverso il proxy e utilizza la stessa transazione e collegamento come Hibernate.

Ho trovato il post del blog Transaction aware datasource (use dbunit & hibernate in spring) spiegando questo.

Un altro approccio sarebbe quello di saltare del tutto i test transazionali e pulire il database invece manualmente. Controlla il mio artcle transactional tests considered harmful.

+0

+1 Bella risposta Tomasz! – Nilesh

0

Sembra che banco di prova ha bisogno di due operazioni: una per mettere i dati nel database, e un secondo per recuperarla.

Quello che vorrei fare è:

  • utilizzare un database di memoria in modo che i dati sono puliti quando termina la prova di unità.
  • Rimuovere le annotazioni transazionali e utilizzare direttamente i metodi beginTransaction e commit della sessione.

Il conteggio iniziale overlaytype sarebbe 0, e dopo la sessione viene salvata, dovrebbe essere 1.

Problemi correlati