我已经阅读了很多关于使用 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 自己打开一个事务,而后者断言失败,因为事务尚未提交。如何在执行最后一个断言之前提交事务?