Весенний интеграционный тест с ручным управлением транзакциями

Я читал много постов и веток о тестировании интеграции со Spring, но ничего не может быть ни полезным, ни полезным.

Мы используем Spring 3.2.3 с Hibernate, Spring Data и базой данных Oracle. Для тестирования мы также используем DbUnit и Spring-test-dbunit. В рабочем коде транзакция запускается контроллером, а сама служба ничего не знает о транзакции.

Итак, вот мой тест:

@ContextConfiguration // ...
@ActiveProfiles // ...
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
    DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    ModifiedDbUnitTestExecutionListener.class })
@DbUnitConfiguration(databaseConnection = "oracleConnection")
@DatabaseSetup("/database/snapshot/snapshot.xml")
public class IntegrationTest extends AbstractTransactionalJUnit4SpringContextTests
{
    @Test
    public void sampleTest()
    {
        // transaction is already started

        this.assertThatNewsContains(0);

        News news1 = new News();
        news1.setTitle("Test News 1");
        News savedNews1 = this.newsService.save(news1);
        Assert.assertTrue(savedNews1.getId() > 0);

        News news2 = new News();
        news2.setTitle("Test News 2");
        News savedNews2 = this.newsService.save(news2);
        Assert.assertTrue(savedNews2.getId() > 0);

        News news3 = new News();
        news3.setTitle("Test News 3");
        News savedNews3 = this.newsService.save(news3);
        Assert.assertTrue(savedNews3.getId() > 0);

        // transaction commit should occur HERE
        // @todo: HOW ?!

        this.assertThatNewsContains(3);
    }

    private void assertThatNewsContains(int newsSize)
    {
        List<News> allNews = this.newsService.getNews();
        Assert.assertEquals(newsSize, allNews.size());
    }

}

Что я узнал, так это то, что если я аннотирую службу новостей с @Transactional(propagation=Propagation.REQUIRES_NEW) тест работает нормально, но не так, как в рабочем режиме. @Transactional(propagation=Propagation.REQUIRED) недостаточно, поскольку DbUnit-Spring-test сам по себе открывает транзакцию, и последнее подтверждает ошибку, так как транзакция еще не зафиксирована. Как я могу добиться, чтобы транзакция была зафиксирована ДО того, как будет выполнено последнее утверждение?

2 ответа

Решение

Я просто хотел показать, как мне наконец удалось выполнить некоторый код в отдельной транзакции.

Тебе нужно

@Autowired
private PlatformTransactionManager          platformTransactionManager;

private TransactionTemplate             transactionTemplate;

в вашем тестовом классе. Тогда вы можете сделать следующее:

this.transactionTemplate = new TransactionTemplate(this.platformTransactionManager);

// note that parameters passed to the transaction must be final!
final Object parameter = something;

Object returnedValue = this.transactionTemplate.execute(new TransactionCallback<Object>()
    {
        @Override
        public Object doInTransaction(TransactionStatus status)
        {
            return doSomethingAndReturnAnObject(parameter);
        }
    }
);

Как указано в документации

http://springtestdbunit.github.io/spring-test-dbunit/

Если вы сконфигурировали тесты DBUnit для запуска с использованием DbUnitTestExecutionListener, а также используете TransactionalTestExecutionListener, у вас могут возникнуть проблемы с транзакциями, которые не запускаются до настройки данных или откатываются до того, как ожидаемые результаты могут быть проверены. Для поддержки тестов @Transactional с DBUnit вы должны использовать класс TransactionDbUnitTestExecutionListener.

И чтобы инициировать транзакцию, вы должны аннотировать свой тестовый метод или класс с помощью аннотации @Transactional, подобной этой.

@Test
@Transactional
    public void sampleTest()
    {
Другие вопросы по тегам