繁体   English   中英

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

[英]NoSuchMethodError: org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass

我有导致错误的测试。 我试图在 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>

如何解决这个问题?

我把jupiter和junit的版本改成5.3.2,问题没有了

添加平台和启动器依赖项后,我能够运行 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>

接下来进行 spring-boot 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>

采用:

<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>

你可以在这里找到更多细节

Maven/Gradle、Eclipse/IntelliJ 使用 Spring Boot 的组合/或不包含 Junit4/Junit5 的组合抛出此 NoSuchMethodError 的不同风格。 这导致许多不同的解决方案,所有这些解决方案只能解决一部分人的问题。 这个冗长的答案试图解释根本原因以及您可以采取的解决问题的步骤,无论您使用的是哪种口味。

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

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

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

解决:
首先,确定运行时正在使用哪个版本的 ReflectionUtils(或它抱怨的其他类)。 这相当容易。 在 Eclipse 中,做一个 Open Type,在 IntelliJ 中,使用导航/转到类。 确保完全限定路径。 如果路径上恰好有 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 - 使用谷歌。 是的,我知道你是通过谷歌来到这里的,但这次改变你的搜索,看看是否有人记录了“这个版本的 JUnit5 在运行时使用这个版本的 ReflectionUtils”或者“这个版本的 IntelliJ 把这个版本的 ReflectionUtils 放在类路径上”或者“此版本的 Spring Boot 将此版本的 ReflectionUtils 放在类路径中”。 请记住,目标是找到在运行时正在使用的类的版本

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

找到运行时使用的 ReflectionUtils 版本后,您需要找出编译时使用的版本

确定哪个 jar ReflectionUtils 位于其中。

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM