Spring 测试中的@Transactional 注释

@Transactional annotation in Spring Test

我正在阅读 Spring 关于 Spring test 的文档:here

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

If your test is @Transactional, it rolls back the transaction at the end of each test method by default. However, as using this arrangement with either RANDOM_PORT or DEFINED_PORT implicitly provides a real servlet environment, the HTTP client and server run in separate threads and, thus, in separate transactions. Any transaction initiated on the server does not roll back in this case.

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

到底是什么意思

感谢任何帮助。

这意味着您的服务器不会回滚您的更改,因为它会 运行 在测试环境之外的另一个环境中。 只会回滚您在测试环境中所做的更改。

例如:

@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 annotation to reset your context, or check Reset database after each test on Spring without using DirtiesContext

edit: following comments on original post, it was not clear whether you needed to use WebEnvironment.RANDOM_PORT or if it was a simple question.
Most likely, if you do not need WebEnvironment.RANDOM_PORT, you can simply use WebEnvironment.MOCK, which runs in the same environment that the JUnit tests, hence would actually rollback.