我有 3 组测试:单元测试、集成测试、验收测试。
@RunWith(SpringRunner.class)
)当我运行“所有测试”时,会启动 2 个不同的应用程序上下文,并且我有重复的队列订阅者。
我知道此订阅者重复的以下解决方法:
在一组测试之后,有什么方便的方法来卸载应用程序上下文吗?
@DirtiesContext
真是绝配spring.test.context.cache.maxSize=1
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestExecutionListeners({FlywayTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public abstract class AcceptanceTest {}
我强烈建议通读这篇文章:https://docs.spring.io/spring-framework/reference/testing/testcontext-framework/ctx-management/caching.html。它很好地解释了 Spring 如何尝试缓存和重用在同一 JVM 中运行的测试上下文。
我看到有两种可能的方法可以解决您的问题。
您设法设置两个测试用例,使它们根据上面文章中描述的规则构建相同的上下文缓存键。在我的一个项目中,我使用
@ActiveProfiles
来实现这一目标。我基本上创建了自己的注释来标记应该共享资源的测试(在您的情况下,您可以将注释命名为 @RegistersQueueSubscribers
),并使用 @SpringBootTest
和 @ActiveProfiles
注释对该注释进行注释。这样,所有使用该注释进行注释的测试类都将激活相应的配置文件,为 Spring 创建特定的上下文缓存键。请注意,这仍然不能保证 100% 缓存有效,因为一个带注释的测试类可以在 Spring 上下文中设置其他内容,生成不同的上下文键。因此,这种方法可能会有所帮助,但取决于您如何设置测试。
您在 Spring 上下文之外管理队列订阅。 Spring 的上下文缓存机制非常好,但不太容易理解和跟踪幕后发生的事情。如果您有像这样的队列这样的关键资源,并且必须确保订阅仅发生一次,那么最好在 Spring 之外进行管理,以便您可以完全控制正在发生的事情。例如,您可以拥有自己的单例来保存所有订阅,以便在多个测试尝试订阅时可以重用它们。但请注意,这可能会带来其他问题,具体取决于您正在做什么。如果测试并行运行并且两个测试竞争消耗同一队列上的消息怎么办?这种竞争条件可能会使您的测试不稳定。