NoSuchMethodError:org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass

时间:2018-12-25 23:26:44

标签: java intellij-idea dependencies junit5 junit-jupiter

我有导致错误的测试。我试图在IntelliJ Idea 2018.3.2中执行它。所有jupiter和junit依赖项都具有版本RELEASE

错误的全文:

Dec 26, 2018 1:17:17 AM org.junit.platform.launcher.core.DefaultLauncher handleThrowable
WARNING: TestEngine with ID 'junit-jupiter' failed to execute tests
java.lang.NoSuchMethodError: org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass(Ljava/lang/String;)Lorg/junit/platform/commons/function/Try;
at org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector.createAbortedExecutionPredicate(OpenTest4JAndJUnit4AwareThrowableCollector.java:40)
at org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector.<clinit>(OpenTest4JAndJUnit4AwareThrowableCollector.java:30)
at org.junit.jupiter.engine.support.JupiterThrowableCollectorFactory.createThrowableCollector(JupiterThrowableCollectorFactory.java:34)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:68)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

该测试具有以下视图

import biz.Services.msg.BookTimeMsgService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertTrue;

@ExtendWith(MockitoExtension.class)
public class MsgReceiverTest {

@Mock
BookTimeMsgService bookTimeMsgService;

@InjectMocks
MsgReceiver msgReceiver;

@Test
public void msgReceiverTest_bookTimeServiceShouldObtainMsg() {
    assertTrue(true);
}

我的pom.xml的一部分

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.1.RELEASE</version>
</parent>

   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>RELEASE</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.junit</groupId>
        <artifactId>junit-bom</artifactId>
        <version>RELEASE</version>
        <type>pom</type>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>RELEASE</version>
        <scope>test</scope>
    </dependency>

如何解决此问题?

5 个答案:

答案 0 :(得分:29)

我将jupiter和junit的版本更改为5.3.2,问题消失了

答案 1 :(得分:18)

添加平台和启动器依赖项后,我能够运行Junit 5测试:

<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-commons -->
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-commons</artifactId>
    <version>1.4.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher -->
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <version>1.4.0</version>
    <scope>test</scope>
</dependency>

答案 2 :(得分:0)

接下来的春季引导2.1.3和junit 5.4.0测试所需的最小pom.xml设置:

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  <parent>
    <groupId>org.springframework.boot</g..roupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath/>
  </parent>

  <properties>
    <junit-jupiter.version>5.4.0</junit-jupiter.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

答案 3 :(得分:0)

使用:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>

代替

<dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <scope>test</scope>
</dependency>
<dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <scope>test</scope>
</dependency>

您可以找到更多详细信息here

答案 4 :(得分:0)

使用Spring Boot的Maven / Gradle,Eclipse / IntelliJ组合/或在包含Junit4 / Junit5时不使用,会引发此NoSuchMethodError不同的味道。这导致了许多不同的解决方案,所有这些解决方案仅解决了一部分人的问题。这个冗长的答案是试图解释根本原因以及可以采取的步骤来解决问题(无论使用哪种口味)。

根本原因:
在编译时,使用了一个版本的ReflectionUtils(我在这里也看到了其他类),而在运行时,使用了另一个版本。运行时版本期望存在某种方法,但是该方法不存在,或者存在具有不同的签名(参数的数量/类型)

请注意,当我说编译时间时,这可能意味着(通常确实如此)表示ReflectionUtils的版本,该版本用于在类路径中编译第三方jar。

解决方案将始终是更改或排除某些jar版本。诀窍是找到哪个jar和哪个版本。

要解决:
首先,确定在运行时使用了哪个版本的ReflectionUtils(或它抱怨的其他类)。这很容易。在Eclipse中,执行IntelliJ中的Open Type,使用导航/转到进行分类。确保完全限定路径。如果您的路径上只有1个版本,那很好。如果路径上的版本多,则您要执行的第一个操作是修改构建路径以排除其中一个版本。

如果您甚至不能临时修改构建路径,则在运行时很难确定正在使用哪个版本的ReflectionUtils。由于JUnit 4和5在开始运行任何代码之前就开始死亡,因此无法插入

CodeSource src = ReflectionUtils.class.getProtectionDomain().getCodeSource();
if (src != null) {
    URL jar = src.getLocation();
    System.out.println(jar.toString());
}

获取运行时jar的位置。但是您可以尝试:

1-创建一个新的新项目,一个新的pom,在其中放入1个junit,然后使用上面的代码运行它,看看结果如何。之所以可行,是因为已删除了非工作项目中的所有冲突。在这种情况下,移至#2可能不起作用。这也可能导致错误的结果,因为新项目的运行时路径可能与非工作项目的运行时路径不同。尝试更新新项目的pom,使其看起来越来越类似于非工作项目的pom。记住,目标是找到运行时正在使用的类的版本

2-使用google。是的,我知道您是使用Google到达这里的,但是这次更改搜索以查看是否有人记录到“此JUnit5版本在运行时使用此版本的ReflectionUtils”或“此版本的IntelliJ将此版本的ReflectionUtils放在类路径上”或“这个版本的Spring Boot将这个版本的ReflectionUtils放在类路径上”。记住,目标是找到运行时正在使用的类的版本

3-劫持课程(高级)。当stacktrace出现时,您将在stacktrace中看到几个类。尝试在Internet上查找该类的源代码,然后在项目中创建该包和类。然后插入上面的代码,并尝试运行失败的测试。

一旦找到运行时使用了哪个版本的ReflectionUtils,就需要找出在编译时使用了哪个版本

确定ReflectionUtils驻留在哪个jar中。

在运行测试时弹出的堆栈跟踪中,确定尝试使用ReflectionUtils失败的顶级类和方法。这是用不兼容版本的ReflectionUtils编译的代码。找出该类在哪个jar中。我将这个罐子称为冲突罐子。尝试获取该冲突jar的依赖关系树。依赖关系树应指示冲突的jar依赖于哪个版本的ReflectionUtils jar。

一旦发现在编译时和运行时使用了哪个版本的ReflectionUtils jar,您可能会发现它们是不同的并且也不兼容。此时,您将必须

1-更改运行时使用的ReflectionUtils jar版本以匹配冲突jar所需的ReflectionUtils版本

2-将冲突的jar版本更改为依赖于运行时路径上的ReflectionUtils jar的相同版本

3-如果冲突的jar是构建路径中某些父jar的依赖项,并且未明确包含在构建路径中,请尝试从父jar中排除冲突的jar,然后显式添加一个新版本。这可能会解决问题-但这当然是首先造成这种混乱的行为类型。

您可以执行的其他操作
如果您知道在项目中同时使用了JUnit4 jar和JUnit5,请尝试从编译时和运行时路径中完全删除其中一个。两种范例的Assert模式差异很大,您可能不想将它们混入同一项目中,因为这可能导致混淆哪些参数是预期结果,消息和被测变量。