23

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

如何解决问题?

4

5 回答 5

41

我把jupiter和junit的版本改成了5.3.2,问题就消失了

于 2018-12-26T21:06:27.640 回答
26

添加平台和启动器依赖项后,我能够运行 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>
于 2019-02-12T14:16:13.260 回答
2

接下来为 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>
于 2019-03-16T15:44:45.887 回答
2

利用:

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

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

于 2019-11-23T12:31:19.343 回答
0

Maven/Gradle、Eclipse/IntelliJ 的组合使用 Spring Boot/或不使用 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 - 使用谷歌。是的,我知道您是通过使用 google 到达这里的,但这次更改您的搜索以查看是否有人记录了“此版本的 JUnit5 在运行时使用此版本的 ReflectionUtils”或“此版本的 IntelliJ 将此版本的 ReflectionUtils 放在类路径上”或“这个版本的 Spring Boot 正在把这个版本的 ReflectionUtils 放在类路径上”。请记住,目标是找出运行时使用的类的版本

3 - 劫持一个类(高级)。当堆栈跟踪出现时,您将在堆栈跟踪中看到几个类。尝试在 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,请尝试从编译时和运行时路径中完全删除其中一个。两种范式的 Assert 模式非常不同,您可能不想将它们混合在同一个项目中,因为这可能会导致混淆哪些参数是预期结果、消息和被测变量。

于 2020-02-10T22:08:49.803 回答