Spring Boot @WebIntegrationTest和TestRestTemplate - 是否可以回滚测试事务?

问题描述 投票:8回答:3

我有一个带Spring Data Rest的Spring Boot应用程序,我在集成测试中使用@WebIntegrationTestTestRestTemplate。测试的基类看起来像这样:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles(profiles = "test")
@SpringApplicationConfiguration(classes = Application.class)
@Transactional
@TransactionConfiguration
@WebIntegrationTest("server.port: 0")
public abstract class IntegrationTest {

   ...

}

我正在使用TestRestTemplate来测试实体的创建,以便对资源执行POST请求。问题是,即使我的测试被配置为事务性的,也不会回滚在数据库上持久保存实体的事务,因此实验在测试后仍保留在数据库中。我有点明白,因为在测试中回滚的事务与持久化实体的事务不同。

现在我的问题是,有没有办法在测试方法中回滚通过RestTemplate发出的请求触发的事务?

spring spring-boot spring-data-rest spring-test
3个回答
22
投票

有没有办法在测试方法中回滚通过RestTemplate发出的请求触发的交易?

不可以。回滚已部署的应用程序管理的事务是不可能的。

当您使用@WebIntegrationTest@SpringApplicationConfiguration注释测试类时,Spring Boot将启动一个嵌入式Servlet容器并在其中部署您的应用程序。因此,从这个意义上说,您的测试和应用程序在两个不同的进程中运行。

Spring TestContext Framework只管理Test-managed transactions。因此,测试类中@Transactional的存在仅影响本地测试管理的事务,而不影响不同进程中的事务。

正如其他人已经提到的那样,解决方法是在测试完成后重置数据库的状态。为此你有几个选择。有关详细信息,请参阅参考手册的Executing SQL scripts部分。

问候,

Sam(Spring TestContext Framework的作者)


0
投票

你可以使用TestRestTemplate而不是使用RestTemplateMockMvc。在这种情况下,@Transactional将回滚数据更改。

如果您正在测试@RestController中的逻辑以进行POST操作,那么MockMvc就足够了。如果您的测试涉及过滤器,那么您可能需要使用TestRestTemplate。在这种情况下,正如其他人指出的那样,您需要在测试结束时重置数据库中的测试数据。


0
投票

我最近需要这个,因为我们的1300多次集成测试花费了大约-70分钟而且它是可行的但是通过一些低级管道。

由于共享测试用例和引导服务器的内存,我通过编写DataSource实现来完成它,该实现仅管理1个连接并将其返回给getConnection()的任何调用者。连接本身是一个Connection实现,它充当真实连接的包装器。 然后将数据源添加到@SpringBootTest配置中。

我不会在这里发布代码(公司财产),但这里是主要的细节:

DataSource将Connection包装器维护为静态字段。 在dataSource.getConnection()上,所有“借用者”的计数器都会递增。 在connection.close()时,此计数器递减。如果它变为0,则表示测试用例已结束,并且事务可以回滚。

有一个问题需要考虑,那就是spring的事务管理:你必须模拟事务回滚。 为此,在每个connection.open()上,我创建一个保存点(connection.setSavePoint())并将其推送到LinkedList中。 Ony任何connection.rollback(),我从堆栈弹出它并执行connection.rollback(savePoint)。

我还必须破解启用提交功能的可能性,因为必须在@BeforeAll()中创建数据库。 我在测试用例中不依赖@Transactional,而是在抽象父代的@Before / @After方法中调用dataSource.getConnection / connection.close()来标记事务边界。

这不是最漂亮的解决方案,但这将测试时间从70分钟减少到30分钟(同时保持测试绿色;)),这是一个不错的胜利。

希望这有助于某人。

© www.soinside.com 2019 - 2024. All rights reserved.