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?Junit3This 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