春季测试中的@Transactional批注

时间:2020-10-29 12:38:59

标签: java spring-transactions spring-test

我正在here

中阅读有关Spring test的Spring文档。

关于在测试中使用@Transactinoal,它说:

如果您的测试是@Transactional,则默认情况下它将在每个测试方法的末尾回滚事务。但是,由于将这种安排与RANDOM_PORT或DEFINED_PORT一起使用隐式提供了一个真正的servlet环境,因此HTTP客户端和服务器在单独的线程中运行,因此在单独的事务中运行。在这种情况下,服务器上启动的任何事务都不会回滚。

我不明白在这种情况下服务器上启动的任何事务都不会回滚。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

这意味着您的服务器不会回滚您的更改,因为它将在测试环境以外的其他环境中运行。 将仅回滚在测试环境中所做的更改。

例如:

@Autowired
private AnyRepository anyRepository;

@Test
@Transactional
void testSave(){
  anyRepository.save(new AnyEntity());
  // Will create an entity from your test environment
}

@Test
@Transactional
void testRead(){
  anyRepository.findAll();
  // Won't find any entities since they were rollbacked
}

相反,如果您使用@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)启动了Spring的本地实例),它将与您的单元测试环境分离,因此:

@Autowired
MockMvc mvc;

@Test
@Transactional
void testSave(){
  mvc.perform(post(/* enough to create an entity */);
  // Your server, detached from test environment, persists the entity
}

@Test
@Transactional
void testRead(){
  mvc.perform(get(/* enough to get that entity */);
  // Will get previously created entity (if testSave was run before)
}

如果要在发送Web请求后回滚,可以使用@DirtiesContext批注来重置上下文,或选中Reset database after each test on Spring without using DirtiesContext

编辑:根据原始帖子的评论,不清楚您是否需要使用WebEnvironment.RANDOM_PORT还是一个简单的问题。
很可能,如果您不需要 WebEnvironment.RANDOM_PORT,则可以简单地使用WebEnvironment.MOCK,它在JUnit测试的相同环境中运行,因此实际上会回滚。