This article is participating in the Java Theme Month – Java Debug Notes Event, see the event link for details
Hi guys, it’s finally Java Theme month! Hey, hey, go!! 😝
Let’s take a look at a strange bug and its problems in this issue.
!!!!!!!!! JUnit Version 3.8 or later Expected:
As shown below, when I was unit testing, the console threw this weird bug!
Three exclamation points at the beginning
Who I am now??
The exception information is as follows:
java.lang.ClassNotFoundException: junit.framework.ComparisonFailure
So first dig into its source code to see what it is pa 😝
Make a breakpoint at line 264 and debug runs
Press Alt+F8 to find out which classes the class loader uses
ClassLoader.getClassLoader(caller)
The effect is as follows: you can see here
As for why I click here, mainly because it is more prominent haha ~
You can see that it has loaded the junit-rt.jar file in the idea plugin directory IntelliJ idea 2020.1\plugins\junit\lib
Hesitated, or continue to explore ha ha
Strange parameters
So I debug all the way down, and finally see this thing, running JUnitStarter’s main function ~
Three variables are passed simultaneously
- -ideVersion5
- -junit3
- Com. Java4ye. Demo. A, contextLoads (class, the test method)
As shown in figure ~
Here we unzip the junit-rt.jar into the junit-rt directory above,
You can quickly find the JUnitStarter with IDEA.
!!!!!!!!! The source of the
Look at the code and find that there is such a call logic ~
if (!"com.intellij.junit5.JUnit5IdeaTestRunner".equals(agentName) && ! canWorkWithJUnitVersion(System.err, agentName)) { System.exit(-3);
}
Copy the code
Soga, this Process finished with exit code-3
canWorkWithJUnitVersion
junitVersionChecks
summary
Can be found if the agent name agentName not com. Intellij. Junit5. JUnit5IdeaTestRunner
I’m going to check the junit version. Then go to load the junit.framework.Com parisonFailure class.
This class is not available in JUnit 5. The architecture of version 5 is more complex. JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
By the way, what this ComparisonFailure does:
Raised when asserting equals for Strings fails
ε=ε=ε=( ̄▽ ̄) there is a mailbox 📫
Why did it happen?Junit3
This is a weird parameter
First of all, the parameter passed is related to this agentName
So here’s the problem!
In my demo, Springboot version 2.4.5 was used, and spring-boot-starter-test was introduced in the POM file with version 5.7, as shown below
You can see that JUnit5 is used
Take a look at the structure of the project with questions
There is A class A with the same name in the test directory and main directory
Under the test of A
package com.java4ye.demo;
//import org.junit.Test;
import org.junit.jupiter.api.Test;
public class A{
@Test
public void contextLoads(a) {
System.out.println("hello"); }}Copy the code
At this point I tried to rename A under test to AA, and strangely it worked, haha, and it did use Junit5
So I did another experiment, import Junit4 package, change AA to A, continue the test, the result is also normal
summary
When using Junit5, if the test class in the test directory has the same name as the package in the main directory, the strange argument -junit3 will be thrown. JUnit Version 3.8 or later Expected:
Here I am also curious why the parameter changed to -junit3, but do not understand how to debug the next look, but not 🐖
episode
java.lang.NoClassDefFoundError:
In find the JUnitStarter class, 4 ye tried to use the command Java JUnitStarter to run, results had thrown the Java. Lang. NoClassDefFoundError:
Java JUnitStarter command to run, the result has thrown the Java. Lang. NoClassDefFoundError:
The difference between
Error: ClassNotFoundException ClassNotFoundException
The biggest difference between the two is:
One is Error and one is Exception haha
Say in detail:
ClassNotFoundException is a non-runtime exception that is detected at compile time and needs to be tried and caught
The Java. Lang. NoClassDefFoundError: it is to belong to the error, the JVM is handling errors.
There is a little detail here
This is the cause of the JDK11 display, before using JDK8 only error line ~ friends can try to yourself
The solution
Ahem, what about this mistake?
In fact, this is the original solution haha
You can see in the decompiled IDEA code above that our JUnitStarter belongs to
package com.intellij.rt.junit; The package.
The correct way to run it is to run it in the same directory as com, as follows
Note that the package name is required when running.
java com.intellij.rt.junit.JUnitStarter
Copy the code
You can see it already appears here!! JUnit Version 3.8 or later Expected
That is the paragraph of abnormal information at the beginning of our article!
After manually put the required package in this directory, it can also work normally ~
Other small experiments and insights are written in the summary below
conclusion
oneUnit tests should be formally named!
Do not introduce different versions of unit test packages
If you use this Junit5 in your project, then use it directly!! JUnit Version 3.8 or later expected This exception
Java.lang. Exception: No runnable methods (junit4
Three. Expansion package to solve doubts
For example, if I import the spring-boot-starter-test in the POM file, it will help me import the junit package of the corresponding version, and I do not know what version of the junit package is introduced. In this case, I can search the extension package of IDEA. You can find the version of junit
Junit3 uses inheritance; Junit4 started with annotations
So, if you want to try ✍ with inheritance, try hahaha
Unit tests are important, mainly to prove that your logic is correct in the scope of the test 😝
I am 4ye, we will see you next time, ヾ( ̄▽ ̄)Bye Bye