2011-12-21 34 views
6

Tengo problemas tratando de realizar cambios en una transacción de Hibernate a la base de datos para que DbUnit funcione correctamente en mi caso de prueba. Parece que DbUnit no está viendo los cambios realizados por Hibernate porque aún no están comprometidos al final de la transacción ... y no estoy seguro de cómo reestructurar mi caso de prueba para que esto funcione.Obteniendo que DbUnit funcione con Hibernate Transaction

Aquí es mi caso de prueba en off simplificado para demostrar mi 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); 
    } 
} 

Mi idea entera en el uso de DbUnit es: -

  • llamada someService.save(...) que guarda los datos en varias tablas.
  • Utilice DbUnit para obtener la tabla esperada de XML.
  • Use DbUnit para obtener la tabla actual de la base de datos.
  • Do Assertion.assertEquals(expectedTable, actualTable);.

Pero, en este punto, no puedo hacer que DbUnit vea los cambios realizados por Hibernate dentro de la transacción.

¿Cómo debo cambiar para que DbUnit funcione bien con la transacción de Hibernate?

Gracias.

Respuesta

9

nunca he trabajado con DbUnit, pero parece que TransactionAwareDataSourceProxy hará el truco. Básicamente lo que necesita para envolver el origen de datos original con este proxy y utilizar en su lugar, por lo que este código:

new DatabaseConnection(dataSource.getConnection()) 

realidad pasa por el proxy y utiliza la misma transacción y la conexión como Hibernate.

Encontré Transaction aware datasource (use dbunit & hibernate in spring) publicación en el blog explicando esto.

Otro enfoque sería omitir completamente las pruebas transaccionales y limpiar la base de datos en lugar de hacerlo manualmente. Mira mi transactional tests considered harmful artcle.

+0

+1 Buena respuesta Tomasz! – Nilesh

0

Parece que el caso de prueba necesita dos transacciones: una para poner datos en la base de datos, y una segunda para recuperarla.

Lo que yo haría es:

  • utiliza una base de datos de memoria para que el se limpia cuando se termina la prueba unitaria.
  • Elimine las anotaciones transaccionales y utilice los métodos beginTransaction y commit de la sesión directamente.

El conteo inicial overlaytype sería 0, y después de la sesión se guarda, debe ser 1.

Cuestiones relacionadas