如何在测试之间关闭应用程序上下文

问题描述 投票:0回答:1

我有 3 组测试:单元测试、集成测试、验收测试。

  • 后两组启动 ApplicationContext:最小用于“集成”,完整用于“接受”。
  • 两个应用程序上下文都注册队列订阅者。
  • 应用程序上下文在整个测试运行结束时取消注册 (
    @RunWith(SpringRunner.class)
    )

当我运行“所有测试”时,会启动 2 个不同的应用程序上下文,并且我有重复的队列订阅者。

我知道此订阅者重复的以下解决方法:

  • 切勿同时运行集成和验收测试
  • 使用“验收”应用程序上下文进行“集成”测试。缺点:试运行需要更长的时间。
  • 添加静态注册表并手动添加/删除监听器。缺点:太复杂且容易忘记

在一组测试之后,有什么方便的方法来卸载应用程序上下文吗?

根据ndrone答案更新

  • @DirtiesContext
    真是绝配
  • 还有一个选项是使用
    spring.test.context.cache.maxSize=1
  • 将缓存的 ApplicationContext 计数限制为 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 {}
spring-boot applicationcontext spring-boot-test
1个回答
0
投票

我强烈建议通读这篇文章:https://docs.spring.io/spring-framework/reference/testing/testcontext-framework/ctx-management/caching.html。它很好地解释了 Spring 如何尝试缓存和重用在同一 JVM 中运行的测试上下文。

我看到有两种可能的方法可以解决您的问题。

选项1

您设法设置两个测试用例,使它们根据上面文章中描述的规则构建相同的上下文缓存键。在我的一个项目中,我使用

@ActiveProfiles
来实现这一目标。我基本上创建了自己的注释来标记应该共享资源的测试(在您的情况下,您可以将注释命名为
@RegistersQueueSubscribers
),并使用
@SpringBootTest
@ActiveProfiles
注释对该注释进行注释。这样,所有使用该注释进行注释的测试类都将激活相应的配置文件,为 Spring 创建特定的上下文缓存键。请注意,这仍然不能保证 100% 缓存有效,因为一个带注释的测试类可以在 Spring 上下文中设置其他内容,生成不同的上下文键。因此,这种方法可能会有所帮助,但取决于您如何设置测试。

选项2

您在 Spring 上下文之外管理队列订阅。 Spring 的上下文缓存机制非常好,但不太容易理解和跟踪幕后发生的事情。如果您有像这样的队列这样的关键资源,并且必须确保订阅仅发生一次,那么最好在 Spring 之外进行管理,以便您可以完全控制正在发生的事情。例如,您可以拥有自己的单例来保存所有订阅,以便在多个测试尝试订阅时可以重用它们。但请注意,这可能会带来其他问题,具体取决于您正在做什么。如果测试并行运行并且两个测试竞争消耗同一队列上的消息怎么办?这种竞争条件可能会使您的测试不稳定。

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