天天看點

!!! JUnit version 3.8 or later expected

小夥伴們好呀,沖沖沖!!😝

本期帶來了一個奇怪的bug~和它帶來的一系列問題,讓我們一起往下看看叭!

!!! JUnit version 3.8 or later expected:

如下所示,當我在進行單元測試時,控制台居然抛出了這麼詭異的bug!

!!! JUnit version 3.8 or later expected

三個感歎号開頭

此刻的我 ???

!!! JUnit version 3.8 or later expected

異常資訊如下:

java.lang.ClassNotFoundException: junit.framework.ComparisonFailure

那麼先挖到它的源碼看個究竟叭 😝

在264行打個斷點,然後debug運作起來

!!! JUnit version 3.8 or later expected

通過

Alt+F8

來擷取這個類加載器 都使用到了哪些類

ClassLoader.getClassLoader(caller)

效果如下:可以看到這裡

!!! JUnit version 3.8 or later expected

至于為啥會點開這裡,主要時因為它比較突出 哈哈~

可以發現它加載了idea 插件目錄

IntelliJ IDEA 2020.1\plugins\junit\lib

中的

junit-rt.jar

檔案

!!! JUnit version 3.8 or later expected

猶豫了下,還是繼續探究下去 哈哈

奇怪的參數

于是我就一路 debug 下來,最後看到這個東東, 運作了

JUnitStarter

main

函數~

同時傳遞了三個變量

  • -ideVersion5
  • -junit3
  • com.java4ye.demo.A,contextLoads (類,測試方法)

如圖~

!!! JUnit version 3.8 or later expected

這裡我們把這個

junit-rt.jar

解壓到上面的這個

junit-rt

目錄,

!!! JUnit version 3.8 or later expected

IDEA

打開 很快就可以找到這個

JUnitStarter

了。

!!! JUnit version 3.8 or later expected

!!!的來源

查閱代碼,發下有這麼一個調用邏輯~

if (!"com.intellij.junit5.JUnit5IdeaTestRunner".equals(agentName) && !canWorkWithJUnitVersion(System.err, agentName)) {
    System.exit(-3);
}
           

Soga , 這個

Process finished with exit code -3

是這麼來的

canWorkWithJUnitVersion

!!! JUnit version 3.8 or later expected

junitVersionChecks

!!! JUnit version 3.8 or later expected

小結

可以發現如果代理名稱

agentName

不是

com.intellij.junit5.JUnit5IdeaTestRunner

就會去 check 這個

junit

版本。 然後去加載這個

junit.framework.ComparisonFailure

類。

tip:

Junit5

中并沒有這個類,版本 5 的架構更複雜,JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

順帶提下這個

ComparisonFailure

的作用:

當斷言equals for Strings失敗時抛出

如下 ε=ε=ε=( ̄▽ ̄) 居然還有郵箱 📫

!!! JUnit version 3.8 or later expected

為何會出現

Junit3

這個奇怪的參數

這裡先解釋下,傳遞的參數乎關系到這個

agentName

!!! JUnit version 3.8 or later expected

那麼問題來了!

在我的 demo 中,使用的

Springboot

版本是

2.4.5

,同時在

pom

檔案中引入了

spring-boot-starter-test

,它的版本号是5.7 ,如下

!!! JUnit version 3.8 or later expected

可以看到明明使用的是

JUnit5

帶着疑問來看看項目的結構是啥樣子叭~

!!! JUnit version 3.8 or later expected

嘿嘿,可以發現這裡

test

目錄下 和

main

目錄中有個 同包同名的類

A

test

下的

A

package com.java4ye.demo;

//import org.junit.Test;

import org.junit.jupiter.api.Test;

public class A{

    @Test
    public void contextLoads() {
        System.out.println("hello");
    }

}
           

這時我嘗試着将這個

test

下的

A

重命名為

AA

,奇怪的是,它正常跑起來了,哈哈,而且确實是用的

Junit5

!!! JUnit version 3.8 or later expected
!!! JUnit version 3.8 or later expected

于是我又做了一個實驗,導入

Junit4

的包,将

AA

改為

A

,繼續測試,結果也是正常的

小結

使用

Junit5

時,如果測試目錄

test

下的測試類和

main

目錄下的同包同名,會出現這個奇怪的參數

-Junit3

, 導緻抛出異常

!!! JUnit version 3.8 or later expected:

這裡我也很好奇為啥參數變成了

-Junit3

,可是不懂要怎麼

debug

看下了,無奈作罷 🐖

插曲

java.lang.NoClassDefFoundError:

在找到這個

JUnitStarter

類時, 4ye 嘗試着用指令

java JUnitStarter

去運作,結果居然抛出了

java.lang.NoClassDefFoundError:

java JUnitStarter

指令去運作,結果居然抛出了

java.lang.NoClassDefFoundError:

!!! JUnit version 3.8 or later expected
差別

不知道小夥伴們對這個

Error

熟不熟悉 哈哈,平時看到的都是

ClassNotFoundException

這兩者最大的差別就是:

一個是

Error

,一個是

Exception

哈哈

詳細點點說:

ClassNotFoundException

是非運作時異常,在編譯期間就檢測出來可能會發生的異常,需要你

try catch

而這個

java.lang.NoClassDefFoundError:

是屬于

error

,是

JVM

處理不了的錯誤。

這裡還有一點點小細節~

就是這個原因是在

JDK11

下才顯示出來的,之前用

JDK8

隻有錯誤一行~ 小夥伴們可以自己嘗試下

!!! JUnit version 3.8 or later expected
解決辦法

咳咳,那這個 錯誤 怎麼解決呢 ?

其實這個也是最原始的解決辦法 哈哈

可以在上面

IDEA

中反編譯出來的代碼看到我們這個

JUnitStarter

是屬于

package com.intellij.rt.junit;

包的 。

那麼我們正确的運作方式就是跑到

com

的同級目錄下去運作 ,如下~

!!! JUnit version 3.8 or later expected

注意這裡運作時要帶上包名(先不帶上那三個參數試試~)

java com.intellij.rt.junit.JUnitStarter
           

可以看到這裡已經出現了

!!! JUnit version 3.8 or later expected

也就是我們文章最開始的那段異常資訊了!

後面手動将需要的包放到這個目錄下,也可以正常運作啦~

其他小實驗和感悟就寫在下面的總結裡啦~

總結

一. 單元測試的命名要規範!

二. 不要引入不同版本的單元測試包

如果項目中使用到這個

Junit5

,此時又直接根據上面

!!! JUnit version 3.8 or later expected

這個異常,引入

Junit4

, 會出現新的異常

java.lang.Exception: No runnable methods

,此時需要你将

@Test

注解修改為

junit4

的版本~ 🐷

三. 擴充包解惑

比如我在

pom

檔案中引入了這個

spring-boot-starter-test

,此時它會幫我導入相應版本的

junit

包 ,而我也不知道它引入了什麼版本的測試包,這時可以在 IDEA 的擴充包中搜尋~,就可以查找到

junit

的版本了~

!!! JUnit version 3.8 or later expected

四. junit3 是使用繼承的方式, Junit4 開始才使用注解的形式

是以,如果你想試試繼承的寫法的話✍,可以試試 哈哈

五. 單元測試很重要,主要是為了證明你的邏輯在這個測試範圍是對的😝

!!! JUnit version 3.8 or later expected

我是4ye,我們下期再見啦,ヾ( ̄▽ ̄)ByeBye

歡迎關注,交個朋友呀!! ( •̀ ω •́ )y

作者簡介 :Java4ye ,很高興認識你!!😝

公衆号: Java4ye 部落客滴個人公衆号~ ,嘿嘿 喜歡就支援下啦 😋

讓我們開始這一場意外的相遇吧!~

歡迎留言!謝謝支援!ヾ(≧▽≦*)o