当前位置: 首页 > 知识库问答 >
问题:

多线程环境集成测试类上使用@Transactional注释的问题

周良弼
2023-03-14

应用程序堆栈:Spring boot 2.1V+测试容器PostgreSQL 1.10.3V+JUnit 4.12V

DB testcontainers配置

@TestConfiguration
public class DatabaseTestConfig {

    private static JdbcDatabaseContainer PSQL;

    static {

        PSQL = (PostgreSQLContainer) new PostgreSQLContainer("mdillon/postgis:9.4").withUsername("test")
                .withPassword("test")
                .withDatabaseName("test");
        PSQL.start();

        Arrays.asList("main_data.sql")
                .forEach(DatabaseTestConfig::restoreDump);

        /*
           set db properties
        */

    }

    public void restoreDump(String fileName){
         /*
           insert sql data 
           PSQL.copyFileToContainer(fileName)...
        */
    }

}

基本集成测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { DatabaseTestConfig.class, ProjectApplication.class })
@ActiveProfiles("test-int")
@AutoConfigureMockMvc
@Sql(scripts = "classpath:extra_data.sql") // insert some extra data for all integration tests
public abstract class AbstractIntTest {
    @Autowired
    protected MockMvc mockMvc;

在任何事情发生的地方调用服务的集成测试

@Transactional
public class SomeIntegrationTest extends AbstractIntTest {


    @Before
    public void setUp() throws IOException {
      //...
    }

    @Test
    public void callServiceTest() throws Exception {
      //mockMvc.perform(post(ENDPOINT_URL)
    }

逻辑简化的服务

@Service
@AllArgsConstructor
public class SomeService {
    private final SomeJpaReporistory repo;
    private final ExecutorService executor;

    @Override
    @Transactional
    public SomeData call(){
        return CompletableFuture.supplyAsync(() -> {
            return repo.findAll(); 
        }, executor).exceptionally(e -> {
            throw new BadRequestException(e.getMessage());
        });
    }

共有1个答案

束帅
2023-03-14

当您将测试变为事务性时,extra_data.SQL中的SQL查询将在事务中执行。该事务绑定到特定的线程,并在测试方法执行之前开始,在测试方法完成后回滚:

  1. 开始事务
  2. 执行extra_data.sql
  3. 调用测试方法
  4. 回滚事务

在第3步中,由于您的服务使用了SupplyAsync,您将在一个单独的线程上调用repo.findall()。由于事务绑定到特定的线程,所以这个findall()调用不是执行extra_data.sql的事务的一部分。为了能够读取extra_data.sql添加的数据,它必须能够读取未提交的更改并执行脏读。Postgres不支持读未提交隔离级别,所以这是不可能的。

 类似资料:
  • 我正在使用多线程执行插入操作。我使用了带注释的方法,我的方法是注释。但我无法执行插入操作,导致出现以下异常。 异常线程"Thread-21"javax.persistence.Transaction必需异常:在org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96)在sun.reflect.Native

  • 问题内容: 我正在使用TestNG使用AbstractTransactionalTestNGSpringContextTests作为基类来测试持久性Spring模块(JPA + Hibernate)。@ Autowired,@ TransactionConfiguration,@ Transactional的所有重要部分都可以正常工作。 当我尝试在带有threadPoolSize = x,invo

  • 我想在Spring中测试注入依赖关系。 我想要一个这样的测试: 我尝试过使用ContextConfiguration和一个测试配置文件,但是测试失败了,我不想在测试中使用@autowired,我想创建我的类的一个实例,并且bean是自动autowired的。

  • 我的 Web 应用程序中出现随机错误,我迷路了。我创建了一个库来解码代码。我尝试了很多,从未失败过测试。但突然间,它开始随机失败。由于它在单线程测试中运行良好,有时在 servlet 环境中失败时,我能想象的唯一解释是问题与多线程环境中使用的库有关。老实说,我知道多线程是一个非常复杂的问题。我担心我的库可能不是线程安全的。顺便说一下,它非常简单,它是一个具有几种静态方法的正面类。基本上,假设您正在

  • 我有一个跨国类,我想让它启用web服务: 我试过: 但是我努力工作,我也尝试过: 当我运行它时,我得到: 线程“main”组织中出现异常。springframework。豆。工厂BeanCreationException:创建在类路径资源[remote application.xml]中定义了名为“cre remoting”的bean时出错:调用init方法失败;嵌套的例外是java。lang.I

  • translated_page: https://github.com/PX4/Devguide/blob/master/en/test_and_ci/jenkins_ci.md translated_sha: 95b39d747851dd01c1fe5d36b24e59ec865e323e Jenkins CI Jenkins continuous integration server on S