1

使用 Spring Boot,我使用 @DirtiesContext 确保在每个测试用例之前清除数据库。

Quarkus AFAIK 没有 @DirtiesContext 注释。相反,建议使用 @TestTransaction。这样,测试用例所做的更改会在测试用例结束时回滚。这适用于单元测试。但是,我正在努力了解如何将其用于集成测试。

我的集成测试使用放心对控制器进行休息调用。一方面,我认为在控制器中使用 @TestTransaction 不是一个好主意。即使我这样做了,当 rest 调用返回时,数据也会被擦除。如果我在控制器中使用@Transaction,我将无法为下一个测试用例擦除数据库。

所以,我的问题是你们如何解决这个问题?在进行集成测试时,如何确保有一个干净的上下文。

4

2 回答 2

2

@TestTransaction 应该启动一个准备好回滚的事务,并且可以传播到白盒测试中的事务方法。但是,当您使用黑盒测试(例如通过放心调用 REST 层)时,您正在调用具有自己的线程池的 Servlet。由于事务与线程相关联,因此您的 REST 调用最终将创建一个新事务,并且该事务将提交(您的 TestTransaction 仅与主线程相关联)。我试图通过手动重置测试数据来解决这个问题。DbUnit 也是一个解决方案。Spring具有相同的行为afaik。

@DirtiesContext 与 DB 事务无关。它是关于 ApplicationContext 以及它的状态是否被操纵(例如,您在一个测试中模拟了一个 bean,而下一个测试需要真实的东西)。需要这个注解的唯一原因是 Spring Boot 默认缓存上下文,而不是为每个测试重新启动。如果您将 jvm 测试 fork-mode 更改为 class,Spring TestContext 将为每个测试类启动,您甚至不会遇到此问题。但是,这意味着您的测试运行速度要慢得多。

正如 Nikos Paraskevopoulos 所提到的,@QuarkusTestProfile 似乎是 Quarkus 的解决方案。基本上分别为每个测试定义 TestContext 。事实上,一个干净的解决方案,您必须自己在 Spring 中实现。我不知道 Quarkus 中是否缓存了多个 TestContext(Spring 会这样做,只要有足够的可用内存),因此按照 Quarkus 指南中提到的顺序排序测试似乎是最好的性能。

于 2021-10-28T20:33:16.333 回答
2

看来春天@DirtiesContext是一个:

指示ApplicationContext与测试关联的测试注释是脏的,因此应该关闭并从上下文缓存中删除。

如果测试修改了上下文,则使用此注解——例如,通过修改单例 bean 的状态、修改嵌入式数据库的状态等。请求相同上下文的后续测试将提供一个新上下文。

这与通过回滚当前事务来清除数据库完全不同:这会破坏并重新创建整个 Spring 上下文。

使用 Quarkus 可以实现相同的效果,此处@QuarkusTestProfile描述为:

如果测试具有与先前运行的测试不同的配置文件,则 Quarkus 将在运行测试之前关闭并使用新配置文件启动。这显然有点慢,因为它增加了测试时间的关闭/启动周期,但提供了很大的灵活性。

但是,如果您只需要确保事务在测试后回滚,那么您需要做的就是用 注释测试方法,而不是控制器io.quarkus.test.TestTransaction如下所述:

您可以在测试中使用标准 Quarkus@Transactional注释,但这意味着您的测试对数据库所做的更改将是持久的。如果您希望在测试结束时回滚所做的任何更改,您可以使用io.quarkus.test.TestTransaction注释。这将在事务中运行测试方法,但在测试方法完成后回滚以恢复任何数据库更改。

您的应用程序代码将在由测试方法启动的事务中运行,然后执行您可以在测试方法中测试的事情,最后回滚以擦除参与事务的任何持久状态。这有一些缺陷:(1)如果在某个时候你的逻辑开始一个新事务,这不会自动回滚。(2) 如果你的逻辑改变了某种不参与事务的状态,这个改变不会回滚。

于 2021-01-09T21:18:24.050 回答