!!! JUnit version 3.8 or later expected

小伙伴们好呀,冲冲冲!!😝

本期带来了一个奇怪的bug~和它带来的一系列问题,让我们一起往下看看叭!

!!! JUnit version 3.8 or later expected:

如下所示,当我在进行单元测试时,控制台居然抛出了这么诡异的bug!

image-20210510221406791

三个感叹号开头

此刻的我 ???

异常信息如下:

java.lang.ClassNotFoundException: junit.framework.ComparisonFailure

那么先挖到它的源码看个究竟叭 😝

在264行打个断点,然后debug运行起来

image-20210511072459885

通过 Alt+F8 来获取这个类加载器 都使用到了哪些类

ClassLoader.getClassLoader(caller)

效果如下:可以看到这里

image-20210511072832306

至于为啥会点开这里,主要时因为它比较突出 哈哈~

可以发现它加载了idea 插件目录 IntelliJ IDEA 2020.1\plugins\junit\lib 中的 junit-rt.jar 文件

img

犹豫了下,还是继续探究下去 哈哈

奇怪的参数

于是我就一路 debug 下来,最后看到这个东东, 运行了 JUnitStartermain 函数~

同时传递了三个变量

  • -ideVersion5
  • -junit3
  • com.java4ye.demo.A,contextLoads (类,测试方法)

如图~

image-20210511080154452

这里我们把这个 junit-rt.jar 解压到上面的这个 junit-rt 目录,

image-20210511203847954

IDEA 打开 很快就可以找到这个 JUnitStarter 了。

image-20210511204053445

!!!的来源

查阅代码,发下有这么一个调用逻辑~

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

Soga , 这个 Process finished with exit code -3 是这么来的

canWorkWithJUnitVersion

image-20210512070528217

junitVersionChecks

image-20210512070721736

小结

可以发现如果代理名称 agentName 不是 com.intellij.junit5.JUnit5IdeaTestRunner

就会去 check 这个 junit 版本。 然后去加载这个 junit.framework.ComparisonFailure 类。

tipJunit5 中并没有这个类,版本 5 的架构更复杂,JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

顺带提下这个 ComparisonFailure 的作用:

当断言equals for Strings失败时抛出

如下 ε=ε=ε=( ̄▽ ̄) 居然还有邮箱 📫

image-20210512071244798


为何会出现 Junit3 这个奇怪的参数

这里先解释下,传递的参数乎关系到这个 agentName

image-20210512075559415

那么问题来了!

在我的 demo 中,使用的 Springboot 版本是 2.4.5 ,同时在 pom 文件中引入了 spring-boot-starter-test ,它的版本号是5.7 ,如下

image-20210512072425629

可以看到明明使用的是 JUnit5

带着疑问来看看项目的结构是啥样子叭~

image-20210512065210618

嘿嘿,可以发现这里 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

image-20210512064803405

img

于是我又做了一个实验,导入 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:

image-20210511204334905

区别

不知道小伙伴们对这个 Error 熟不熟悉 哈哈,平时看到的都是 ClassNotFoundException

这两者最大的区别就是:

一个是 Error ,一个是 Exception 哈哈

详细点点说:

ClassNotFoundException 是非运行时异常,在编译期间就检测出来可能会发生的异常,需要你 try catch

而这个 java.lang.NoClassDefFoundError: 是属于 error ,是 JVM 处理不了的错误。

这里还有一点点小细节~

就是这个原因是在 JDK11 下才显示出来的,之前用 JDK8 只有错误一行~ 小伙伴们可以自己尝试下

image-20210511205557300

解决办法

咳咳,那这个 错误 怎么解决呢 ?

其实这个也是最原始的解决办法 哈哈

可以在上面 IDEA 中反编译出来的代码看到我们这个 JUnitStarter 是属于

package com.intellij.rt.junit; 包的 。

那么我们正确的运行方式就是跑到 com同级目录下去运行 ,如下~

image-20210511212006742

注意这里运行时要带上包名(先不带上那三个参数试试~)

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 的版本了~

image-20210512082317501

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

所以,如果你想试试继承的写法的话✍,可以试试 哈哈

五. 单元测试很重要,主要是为了证明你的逻辑在这个测试范围是对的😝

image-20210509223025707

我是4ye,我们下期再见啦,ヾ( ̄▽ ̄)ByeBye

欢迎关注,交个朋友呀!! ( •̀ ω •́ )y

作者简介 :Java4ye ,很高兴认识你!!😝

公众号: Java4ye 博主滴个人公众号~ ,嘿嘿 喜欢就支持下啦 😋

让我们开始这一场意外的相遇吧!~

欢迎留言!谢谢支持!ヾ(≧▽≦*)o

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值