【问题标题】:Running Spring tests in parallel with maven与 maven 并行运行 Spring 测试
【发布时间】:2013-05-07 09:07:03
【问题描述】:

我有一组使用SpringJUnit4ClassRunner 运行的集成测试。我正在尝试使用 maven surefire 并行运行这些。但是,我注意到代码在进入CacheAwareContextLoaderDelegate.loadContext() 中的同步块之前就被阻塞了。

有没有办法绕过这个缓存?我试过这样做,但似乎有更多的共享状态而不仅仅是缓存本身,因为我的应用程序在 Spring 代码中死锁了。或者是否可以通过在地图键上而不是整个地图上以某种方式同步来使同步更加细粒度?

我对并行化测试的动机是双重的:

  1. 在某些测试中,我将 bean 替换为 mock。由于 mock 本质上是有状态的,因此我必须使用 @DirtiesContext 为每个测试方法构建一个新的 ApplicationContext。
  2. 在其他测试中,我只想部署 Jersey 资源的一个子集。为此,我指定了 Spring 配置类的一个子集。由于 Spring 使用 MergedContextConfiguration 作为上下文缓存中的键,这些测试将无法共享 ApplicationContexts。

【问题讨论】:

标签: multithreading spring integration-testing


【解决方案1】:

如果您禁用并行测试执行,您的测试套件可能会获得更好的周转时间。在 Spring 的参考文档的测试章节中有一段关于Context caching:

一旦 TestContext 框架为测试加载 ApplicationContext(或 WebApplicationContext),该上下文将被缓存并重用于在同一测试套件中声明相同唯一上下文配置的所有后续测试。

为什么要这样实现?

这意味着加载应用程序上下文的设置成本只发生一次(每个测试套件),并且后续测试执行速度要快得多。

缓存是如何工作的?

Spring TestContext 框架将应用程序上下文存储在静态缓存中。这意味着上下文实际上存储在静态变量中。换句话说,如果测试在不同的进程中执行,静态缓存将在每次测试执行之间被清除,这将有效地禁用缓存机制。

要从缓存机制中受益,所有测试都必须在同一进程或测试套件中运行。这可以通过在 IDE 中作为一个组执行所有测试来实现。同样,在使用构建框架(如 Ant、Maven 或 Gradle)执行测试时,确保构建框架不会在测试之间分叉很重要。 例如,如果将 Maven Surefire 插件的 forkMode 设置为 always 或 pertest,TestContext 框架将无法缓存测试类之间的应用程序上下文,从而导致构建过程运行速度明显变慢。

【讨论】:

  • 谢谢,我想我不会阅读文档中的那一段。我更新了我的问题以解释我并行化的动机。希望the bug I reported 能尽快得到修复。
  • @hertzsprung 我建议您创建一个单独的模拟应用程序上下文(或一个包含模拟的测试profile),它可以被其他测试缓存和重用(如果您可以reset()模拟对象的状态,例如在@Before 或@After。阅读可以在我的blog post 中找到更多信息。
【解决方案2】:

我能想到的一件简单的事情是使用@DirtiesContext

【讨论】:

  • 谢谢,我知道那个注释。它可以清除测试类或测试方法之间的上下文,但据我所知并不能避免全局锁。
  • 没错,在我看来,使用@DirtiesContext 应该被视为一种反模式。
猜你喜欢
  • 1970-01-01
  • 2021-05-16
  • 1970-01-01
  • 2015-10-19
  • 1970-01-01
  • 2012-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多