Java Maven surefire插件测试在Jenkins build中失败,但在本地成功运行?

Java Maven surefire插件测试在Jenkins build中失败,但在本地成功运行?,java,maven,unit-testing,jenkins,maven-surefire-plugin,Java,Maven,Unit Testing,Jenkins,Maven Surefire Plugin,我有一个maven项目,通过maven surefire插件执行测试。我观察到并一直在处理的一个奇怪现象是,在本地运行 mvn clean install 它执行我的测试,生成一个成功的版本,其中0个失败,0个错误 现在,当我将此应用程序部署到Jenkins试图构建的远程repo时,我会收到各种随机EasyMock错误,通常是: java.lang.IllegalStateException: 3 matchers expected, 4 recorded. at org.easymock.i

我有一个maven项目,通过maven surefire插件执行测试。我观察到并一直在处理的一个奇怪现象是,在本地运行

mvn clean install
它执行我的测试,生成一个成功的版本,其中0个失败,0个错误

现在,当我将此应用程序部署到Jenkins试图构建的远程repo时,我会收到各种随机EasyMock错误,通常是:

java.lang.IllegalStateException: 3 matchers expected, 4 recorded. at org.easymock.internal.ExpectedInvocation.createMissingMatchers
这是一个被继承的遗留应用程序,我们知道,如果不是简单地错误地使用EasyMock,那么这些测试中的许多都是有缺陷的,但我所处的状态是,通过测试执行,我在本地获得了成功的构建,但在Jenkins中没有

我知道这些测试的执行顺序无法保证,但我想知道如何反思Jenkins build pipeline与local的不同之处,以帮助识别问题

我能做些什么来强制执行本地测试吗?在这一点上,我只是排除了许多麻烦的测试类,但似乎无论我看到Jenkins失败多少次,我要么修复了问题,要么排除了测试类,我只发现它抱怨了一些以前没有提到的其他测试类


如何处理这种情况?JUnit测试运行顺序是不确定的

Java和Maven在这两台机器上的版本相同吗?如果是,请确保您使用的是最新的maven surefire插件版本。另外,确保使用带有Maven构建步骤的Freestyle Jenkins作业,而不是Maven项目类型。使用正确的Jenkins构建类型可以直接修复构建问题,或者为您提供更好的错误,以便您能够诊断实际问题

您可以打开Maven调试日志记录来查看正在运行的顺序测试。每个测试都应该设置(或者删除)自己的测试数据,以确保测试可以独立运行。也许看到测试顺序会给你一些线索,说明哪些类不适当地依赖于其他类。并且-如果应用程序使用缓存,请确保在测试之间清除缓存(或者根据测试需要显式填充)。还要考虑每次运行测试一个包来隔离罪犯——多个SuRoFILE插件执行可能是有用的。 同时检查应用程序是否存在类路径问题。有一些清理类路径的建议


另一种可能性是:切换到JUnit的更高版本可能会有所帮助,除非应用程序使用的是Spring2.5.6.x。如果应用程序正在使用Spring2.5.6.x,并且无法升级,那么可能使用的JUnit4.x的最高版本是4.4。JUnit的更高版本是,并且可能导致难以诊断的测试错误。

我也尝试过类似的情况,我的原因显然是测试实现中的一些并发问题

在阅读您的评论之后:


我实际上做了什么来修复它(就像魔术一样,我是对的吗?)是针对maven surefire插件,我设置了属性reuseForks=false,以及forkCount=1C,这仅仅是1*(机器的CPU数量)

。。。我更确信您的测试存在并发性问题。并发性不容易诊断,特别是当您的实验在一个CPU上运行正常时。但是,当您在另一个系统(通常更快或更慢)上运行它时,可能会出现竞争条件

我强烈建议您逐个检查您的测试,并确保每个测试在逻辑上是隔离的:

  • 它们不应依赖于预期的先前状态(文件、数据库等)。相反,他们应该在每次执行之前准备好适当的设置
  • 如果它们同时修改可能干扰其他测试执行(文件、数据库、单例等)的公共资源,则必须根据需要同步每个断言,并考虑到其初始状态未知:
错误测试:

MySingleton.getInstance().put(myObject);
assertEquals(1, MySingleton.getInstance().size());
正确测试:

synchronized(MySingleton.getInstance())
{
    MySingleton.getInstance().put(myObject);
    assertTrue(MySingleton.getInstance().contains(myObject));
}
审查的一个良好起点是检查一个失败的测试,并向后跟踪执行情况,以找到失败的根本原因


明确设置测试顺序不是一个好的实践,即使我知道这是可能的,我也不会推荐给您,因为它只会隐藏问题的实际原因。想想看,在真实的生产环境中,执行顺序通常是不确定的。

我实际做的是修复它(就像魔术一样,我是对的吗?)是针对maven surefire插件,我设置了属性reuseForks=false,forkCount=1C,这只是1*(机器的CPU数量)。完全同意这里所说的一切,您确定的问题实际上是许多测试的问题,如果不是大多数的话。然而,有成百上千的测试和重写或重构,许多测试是我们现在没有时间做的事情。同样不幸的是,修复它们也很不容易,因为许多在构建中失败的测试都在本地成功了,错误通常来自EasyMock,并且通常描述不够详细,不容易诊断。是的,我明白了。。。嗯,您尝试使用
reuseForks
forkCount
已经足够聪明了。还可以查看
threadCount*
parallel
参数: