Spring 测试:测试类之间的上下文配置缓存的奇怪行为?

Posted

技术标签:

【中文标题】Spring 测试:测试类之间的上下文配置缓存的奇怪行为?【英文标题】:Spring test : strange behavior of context config caching between test classes ? 【发布时间】:2015-04-15 11:03:26 【问题描述】:

我正在为 Spring Integration 项目编写测试,但遇到了一些奇怪的事情:我已经阅读了 Spring 如何缓存测试之间的上下文以及我们如何使用 @DirtiesContext 注释强制清理缓存。但是,我无法解释我观察到的行为,这让我觉得这可能是一个错误......

我有 2 个不同的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations =  "classpath:myInterface-core.xml",
                                    "classpath:myInterface-datasource-test.xml")
public class PropertyConfigurerTest 


   @Test
   public void shouldResolvePropertyForOutPutFile()

   

(它什么都不做,只是故意加载上下文)

还有一个更复杂的实际测试(在下面的 sn-p 中跳过它们):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = 
 "classpath:myInterface-core.xml",
 "classpath:myInterface-rmi.xml",
 "classpath:myInterface-datasource-test.xml")
public class MontranMessagesFlowTest 
...

如您所见,这两个测试加载的配置并不完全相同:第二个测试加载第一个不需要的额外配置文件。

当我一个接一个地运行这两个测试时,第二个测试失败了:简而言之,测试的目标是在 inMemory DB 中插入 2 行,启动我的 Spring 集成流程并使用侦听器断言(在jms:listener-container) 我在出站端收到了 2 条 JMS 消息。我在调试模式下看到实际上 2 条消息没有发送到同一个侦听器,所以我收到一条消息而不是我期望的 2 条消息。不知何故,我在第一次测试中加载了上下文的一些元素(即使我没有对它们做任何事情)对第二次测试产生了影响。

我找到了 2 种不同的解决方法:

在我的第一次测试中添加 @DirtiesContext(classMode=ClassMode.AFTER_CLASS)。 修改我在第一个测试中加载的 Spring 文件列表,使其与第二个测试中定义的完全匹配。

但是,我仍然不明白其中的原理,而且对我来说这似乎是一个错误。

我正在使用 Spring Test 4.1.4.RELEASE。我已将必要的最少代码放在一个单独的项目中以便能够重现。如果需要,我可以分享。

有人对此有解释吗?有没有BUG?

谢谢

文森特

【问题讨论】:

不,不是。你有一个单一的数据库,有 2 个实例来监听......所以你基本上有这个设置的竞争消费者...... 你为什么说我有“2个听东西的实例”?测试不是并行运行的,而是一个接一个地运行。当第一个测试结束时,Spring Integration 流程被关闭。但是当它在第二次测试中再次开始时,我有一个来自第一次测试的“幽灵”监听器。 因为上下文被缓存了......它仍然存在,其中的 bean 也是如此(假设您在一次运行中同时运行两个测试)。 查看我的回答,我们已经开始在所有 SI 测试中添加@DirtiesContext,以确保停止活动组件。 很抱歉,但我仍然遗漏了一些东西:我知道它已被缓存,但在这种情况下,为什么它会在第二次测试期间创建它的另一个实例?为什么设置完全相同的配置会使其工作? 【参考方案1】:

@M。 Deinum 在他的评论中是正确的。

值得一提的是,在 Spring Integration 框架测试本身中,我们已开始将 @DirtiesContext 添加到所有测试中,以确保在测试完成后始终停止任何活动组件(例如入站消息驱动的适配器)。

这也提高了大型测试套件的性能/内存使用率。

【讨论】:

为什么它会提高大型测试套件的性能/内存使用率?不是相反吗,因为通过使用@DirtiesContext,您可以防止缓存并强制所有测试类重新加载所有内容? 只有在多个测试中使用 SAME 上下文时缓存上下文才有意义。在您的情况下,您使用的是不同的上下文,而“其他”则在后台运行。

以上是关于Spring 测试:测试类之间的上下文配置缓存的奇怪行为?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 集成测试:@AutoConfigureMockMvc 和上下文缓存

Java Spring Boot 测试:如何从测试上下文中排除 java 配置类

如何调试,为啥 Spring Boot 集成测试上下文没有在测试之间重用?

即使加载失败,也要在 Spring 测试中缓存上下文

Spring Boot:测试包含 Java 时间的 ResponseEntity

带有 DB 的 Spring Boot 应用程序 - 使用 @DirtiesContext 重新创建上下文后测试类失败