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