【问题标题】:Getting DbUnit to Work with Hibernate Transaction让 DbUnit 与 Hibernate Transaction 一起工作
【发布时间】:2012-01-25 08:43:12
【问题描述】:

我在尝试将 Hibernate 事务中所做的更改推送到数据库以使 DbUnit 在我的测试用例中正常工作时遇到问题。似乎 DbUnit 没有看到 Hibernate 所做的更改,因为它们尚未在事务结束时提交......而且我不确定如何重组我的测试用例以使其正常工作。

这是我的过度简化的测试用例来证明我的问题:-

@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 事务很好地配合?

谢谢。

【问题讨论】:

    标签: java hibernate spring junit dbunit


    【解决方案1】:

    我从未使用过 DbUnit,但似乎 TransactionAwareDataSourceProxy 可以解决问题。基本上你需要用这个代理包装你的原始数据源并使用它,这样这段代码:

    new DatabaseConnection(dataSource.getConnection())
    

    实际上是通过代理并使用与 Hibernate 相同的事务和连接。

    我发现 Transaction aware datasource (use dbunit & hibernate in spring) 博客文章对此进行了解释。

    另一种方法是完全跳过事务测试并手动清理数据库。查看我的transactional tests considered harmful 文章。

    【讨论】:

      【解决方案2】:

      看起来该测试用例需要两个事务:一个用于将数据放入数据库,另一个用于检索它。

      我会做的是:

      • 使用内存数据库,以便在单元测试结束时清理数据。
      • 去掉事务注解,直接使用会话的beginTransaction和commit方法。

      最初的overlaytype计数为0,会话保存后应为1。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-19
        • 2016-12-13
        • 2016-10-06
        • 2011-11-30
        • 2014-02-19
        • 2011-09-03
        • 2013-05-01
        • 2018-05-30
        相关资源
        最近更新 更多