使用Maven并行运行Spring测试

9
我有一个使用SpringJUnit4ClassRunner运行的集成测试集合。我想使用Maven Surefire实现并行运行。然而,我注意到代码在进入CacheAwareContextLoaderDelegate.loadContext()中的同步块之前被阻塞。
有没有绕过这个缓存的方法?我尝试过这样做,但似乎共享状态不仅仅是缓存本身,因为我的应用程序在Spring代码内发生了死锁。或者可以通过某种方式在地图键上同步而不是整个地图来使同步更加精细化吗?
我并行化测试的动机有两个:
  1. 在一些测试中,我用模拟替换了Bean。 由于模拟本质上是有状态的,我必须为每个测试方法构建一个新的ApplicationContext,使用@DirtyContext。在其他测试中, 我只想部署Jersey资源的子集。 为此,我指定了一些Spring配置类的子集。 由于Spring将MergedContextConfiguration用作上下文缓存中的键,这些测试将无法共享ApplicationContexts。

我已经为此提交了一个错误报告 - hertzsprung
2个回答

7
如果禁用并行测试执行,您的测试套件可能会获得更快的反应时间。在Spring参考文档的测试章节中,有一个关于上下文缓存的段落:
一旦TestContext框架为测试加载了ApplicationContext(或WebApplicationContext),该上下文将被缓存并重用于同一测试套件内声明相同唯一上下文配置的所有后续测试。
为什么要这样实现?
这意味着只有在每个测试套件中第一次加载应用程序上下文时才会产生设置成本,并且随后的测试执行速度更快。
缓存是如何工作的?
Spring TestContext框架将应用上下文存储在静态缓存中。这意味着上下文实际上存储在静态变量中。换句话说,如果测试在单独的进程中执行,则静态缓存将在每个测试执行之间清除,这将有效地禁用缓存机制。
要从缓存机制中受益,所有测试必须在同一个进程或测试套件中运行。这可以通过在IDE中作为一组执行所有测试来实现。同样,在使用Ant、Maven或Gradle等构建框架执行测试时,重要的是要确保构建框架在测试之间不进行分叉。例如,如果Maven Surefire插件的forkMode设置为always或pertest,则TestContext框架将无法在测试类之间缓存应用程序上下文,并且构建过程将因此显着变慢。

谢谢,我不认为我在文档中读到过那段话。我已经更新了我的问题,以解释我的并行动机。希望我报告的错误很快就会得到修复。 - hertzsprung
1
@hertzsprung 我建议你创建一个单独的模拟应用上下文(或者一个包含模拟对象的测试配置文件),可以被其他测试缓存和重复使用(如果你在@Before@After中重置模拟对象的状态,那么这是可能的)。更多信息请参阅我的博客文章 - matsev

0

我能想到的一个简单的方法是使用@DirtiesContext


1
谢谢,我知道那个注解。它可以清除测试类或测试方法之间的上下文,但据我所知并不能避免全局锁。 - hertzsprung
在我看来,使用@DirtiesContext应该被视为反模式。 - Marcin Erbel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接