天天看点

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