使用Spring事务进行JUnit多线程测试

时间:2016-04-10 19:30:11

标签: java spring multithreading junit transactions

我正在运行一个JUnit集成测试,内存H2数据库配置如下:

@Bean
public DataSource dataSource() {

    try {
        SimpleDriverDataSource simpleDriverDataSource = new SimpleDriverDataSource();
        simpleDriverDataSource.setDriverClass((Class<? extends Driver>) ClassUtils.forName("org.h2.Driver", this.getClass().getClassLoader()));
        simpleDriverDataSource.setUrl("jdbc:h2:file:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;MVCC=true;FILE_LOCK=NO;mv_store=false");
        simpleDriverDataSource.setUsername("sa");
        simpleDriverDataSource.setPassword("");

        return simpleDriverDataSource;
    } catch(ClassNotFoundException e) {
        throw new IllegalStateException(e.getMessage());
    }

}

测试调用服务方法。此服务方法使用执行程序服务来分叉处理。在调用服务类之前,测试方法将一些数据插入到数据库中,并且可以使用服务(通过JPA存储库调用)读取此数据,直到任务提交给执行程序服务。但是,在运行任务时,它无法读取先前保留的数据。

如何让分叉线程看到持久数据?

注意:这只是单元测试失败,它在运行时工作正常。

1 个答案:

答案 0 :(得分:5)

假设您的测试是@Transactional,您所看到的是预期的行为,因为您(通常)不希望测试所做的更改对系统的其他部分可见,并且可能会滚动回到测试结束时。

解决此问题的一种简单方法是注释@Test方法,如此

@Test
@Transactional(propagation = Propagation.NEVER)
public void testYourLogics() { /* ... */ }

我已经能够在没有propagation = Propagation.NEVER的情况下重现巡回行为,并且看到它已经解决了。

请注意,您必须在运行测试后手动将数据库还原到 clean 状态,否则该测试所做的更改将对其他测试可见