7

我已经阅读了很多关于使用 Spring 进行集成测试的帖子和主题,但没有什么是令人满意或有帮助的。

我们使用带有 Hibernate、Spring Data 和 Oracle 数据库的 Spring 3.2.3。对于测试,我们还使用 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)测试注释 NewsService 工作正常,但它与生产模式不同。@Transactional(propagation=Propagation.REQUIRED)是不够的,因为 DbUnit-Spring-test 自己打开一个事务,而后者断言失败,因为事务尚未提交。如何在执行最后一个断言之前提交事务?

4

2 回答 2

7

我终于设法在单独的事务中执行了一些代码。

你需要

@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);
        }
    }
);
于 2016-12-20T16:02:50.557 回答
0

如文档中所述

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

如果您已将 DBUnit 测试配置为使用 DbUnitTestExecutionListener 运行并且还使用 TransactionalTestExecutionListener,您可能会遇到事务在设置数据之前未启动或在验证预期结果之前回滚的问题。为了使用 DBUnit 支持 @Transactional 测试,您应该使用TransactionDbUnitTestExecutionListener类。

并且要启动事务,您必须像这样使用 @Transactional 注释来注释您的测试方法或类。

@Test
@Transactional
    public void sampleTest()
    {
于 2015-08-10T08:48:03.490 回答