Как заставить DbUnit работать с транзакцией Hibernate - PullRequest
6 голосов
/ 21 декабря 2011

У меня возникла проблема при попытке отправить изменения, внесенные в транзакции 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?

Спасибо.

Ответы [ 2 ]

9 голосов
/ 21 декабря 2011

Я никогда не работал с DbUnit, но, похоже, TransactionAwareDataSourceProxy поможет. По сути, вам нужно обернуть исходный источник данных этим прокси и использовать его, чтобы этот код:

new DatabaseConnection(dataSource.getConnection())

фактически проходит через прокси и использует ту же транзакцию и соединение, что и Hibernate.

Я нашел Источник данных с поддержкой транзакций (используйте dbunit & hibernate весной) сообщение в блоге, объясняющее это.

Другой подход заключается в том, чтобы вообще пропустить транзакционные тесты и очистить базу данных вручную. Проверьте мои транзакционные тесты, считающиеся вредными artcle.

0 голосов
/ 21 декабря 2011

Похоже, что для этого тестового примера требуются две транзакции: одна для помещения данных в базу данных, а вторая для их получения.

Я бы сделал следующее:

  • Используйте базу данных памяти, чтобы очистить данные после завершения модульного теста.
  • Удалите аннотации транзакций и используйте beginTransactionи фиксировать методы сеанса напрямую.

Начальный счетчик типа оверлея будет равен 0, а после сохранения сеанса он должен быть равен 1.

...