2011-12-21 66 views
6

我在嘗試將在Hibernate事務中所做的更改推送到數據庫以使DbUnit在我的測試用例中正常工作時出現問題。看起來DbUnit沒有看到Hibernate所做的更改,因爲它們並沒有在事務結束時被提交......而且我不確定如何重構我的測試用例以使其正常工作。讓DbUnit與休眠事務一起工作

這裏是我過於簡單的測試用例來證明我的問題: -

@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); 
    } 
} 

我使用DbUnit的整體思路是: -

  • 呼叫someService.save(...),節省了數據到幾個表。
  • 使用DbUnit從XML獲取預期表。
  • 使用DbUnit從數據庫中獲取實際表格。
  • Assertion.assertEquals(expectedTable, actualTable);

但是,在這一點上,我無法讓DbUnit查看Hibernate在事務中所做的更改。

我應該如何更改以使DbUnit與Hibernate事務很好地協同工作?

謝謝。

回答

9

我從來沒有用DbUnit的工作,但它似乎像TransactionAwareDataSourceProxy會做的伎倆。基本上你需要用這個代理來包裝自己的原始數據源,並用它來代替,讓這樣的代碼:

new DatabaseConnection(dataSource.getConnection()) 

實際上經過代理服務器,並使用相同的事務和連接的休眠。

我找到Transaction aware datasource (use dbunit & hibernate in spring)博客文章解釋這一點。

另一種方法是完全跳過事務性測試並手動清理數據庫。看看我的transactional tests considered harmful artcle。

+0

+1好的答案Tomasz! – Nilesh 2012-01-01 13:11:36

0

看起來測試用例需要兩個事務:一個用於將數據放入數據庫,另一個用於檢索數據。

我會做的是:

  • 所以當單元測試結束數據清洗使用內存數據庫。
  • 刪除事務註釋並直接使用會話的beginTransaction和commit方法。

初始overlaytype計數是0,會話被保存後,它應該是1