带有手动事务管理的Spring集成测试

act*_*ctc 6 spring transactions spring-test-dbunit

我已经阅读了许多有关使用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());
    }

}
Run Code Online (Sandbox Code Playgroud)

我发现的是,如果我用@Transactional(propagation=Propagation.REQUIRES_NEW)测试对NewsService进行注释可以正常工作,但是它与生产模式下并不相同。@Transactional(propagation=Propagation.REQUIRED)这是不够的,因为DbUnit-Spring-test本身会打开一个事务,而后者的断言将失败,因为该事务尚未提交。如何在执行最后一个断言之前实现事务已提交?

act*_*ctc 6

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

你需要

@Autowired
private PlatformTransactionManager          platformTransactionManager;

private TransactionTemplate             transactionTemplate;
Run Code Online (Sandbox Code Playgroud)

在您的测试课中。然后,您可以执行以下操作:

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);
        }
    }
);
Run Code Online (Sandbox Code Playgroud)