I have the test that leads to error. I tried to execute it in the IntelliJ Idea 2018.3.2
. All jupiter and junit dependencies have version RELEASE
use:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>
instead
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
you can find more details here
Combos of Maven/Gradle, Eclipse/IntelliJ using Spring Boot/or not while including Junit4/Junit5 throw different flavors of this NoSuchMethodError. This leads to many different solutions all of which only fix a portion of people's problems. This long winded answer is an attempt to explain the root cause and steps you can take to fix your problem whichever flavor you are using.
Root cause:
At compile time, one version of ReflectionUtils (I've seen other classes here too) was used, and at runtime, a different one was used. The runtime version was expecting a certain method to exist, but either it didn't exist, or it existed with a different signature (number/type of parameters)
Note, when I say compile time, this can mean (and usually does) mean the version of ReflectionUtils that was used to compile a third party jar inside your classpath.
The solution will always be to change or exclude some version of some jar. The trick is to find which jar and which version.
To solve:
First, identify what version of ReflectionUtils (or other class it is complaining about) is being used at runtime. This is fairly easy. In eclipse, do an Open Type, in IntelliJ, use a navigate/go to class. Make sure to fully qualify the path. If you have exactly 1 version on the path, this is good. If you have more than on version on the path, your first action to take is to modify your build path to exclude one of the versions.
If you cannot modify the build path, even temporarily, it is harder to identify what version of ReflectionUtils is being used at runtime. Since JUnit 4 and 5 begins and dies before you can run any of your code, you cannot insert a
CodeSource src = ReflectionUtils.class.getProtectionDomain().getCodeSource();
if (src != null) {
URL jar = src.getLocation();
System.out.println(jar.toString());
}
to get the location of the runtime jar. But you can try:
1 - create a fresh new project, a fresh pom, put 1 junit inside of it, and run it with the above code and see what comes out. This may work because whatever conflict was in the non working project has been removed. This may not work in which case move to #2. This also may give a false result because the runtime path of a fresh project may be different than that of the non working project. Try updating the pom of the fresh project to look more and more like that of the non working project. Remember, the goal is to find what version of the class is being used at runtime
2 - Use google. Yah I know you got here by using google but this time change your search to see if someone documented "This version of JUnit5 uses this version of ReflectionUtils at runtime" or "This version of IntelliJ puts this version of ReflectionUtils on the classpath" or "This version of Spring Boot is putting this version of ReflectionUtils on the classpath". Remember, the goal is to find what version of the class is being used at runtime
3 - Hijack a class (advanced). When the stacktrace comes out, you will see several classes in the stacktrace. Try to find the source code for the class on the internet and create that package and class in your project. Then insert the code above and try to run the test which was failing.
Once you have found which version of ReflectionUtils is used at runtime, you need to find out what version was used at compile time
Identify which jar ReflectionUtils lives inside.
In the stacktrace which pops out when you run your test, identify the top class and method which died trying to use ReflectionUtils. This is the code which was compiled with an incompatible version of ReflectionUtils. Find out what jar that class is inside. I'll call this jar the conflicting jar. Try and get a dependency tree for that conflicting jar. The dependency tree should indicate which version of the ReflectionUtils jar the conflicting jar was dependent on.
Once you have found which version of ReflectionUtils jar was used at compile time and runtime, you likely will see that they are different and also incompatible. At this point, you will have to
1 - change the version of the ReflectionUtils jar used at runtime to match the version of ReflectionUtils needed by the conflicting jar
2 - change the version of the conflicting jar to one which is dependent on the same version of the ReflectionUtils jar which is on the runtime path
3 - if the conflicting jar is a dependency of some parent jar in build path and not explicity included by your build path, try excluding the conflicting jar from the parent jar and add a newer version explicitly. This may solve the problem - but this is, of course, the type of behavior which created this mess in the first place.
Other actions you can take:
If you know that you are using both JUnit4 jars as well as JUnit5 in your project, try removing one or the other completely from the compile time and runtime paths. The Assert patterns of the two paradigms are different enough that you likely do not want to mix them in the same project as it could lead to confusion of which parameters are the expected results, the message, and the variable under test.
minimal required pom.xml setup for spring-boot 2.1.3 and junit 5.4.0 testing next:
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<parent>
<groupId>org.springframework.boot</g..roupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/>
</parent>
<properties>
<junit-jupiter.version>5.4.0</junit-jupiter.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
I changed the version of jupiter and junit to 5.3.2 and the problem has gone
I was able to run the Junit 5 tests after adding the platform and launcher dependency:
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-commons -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<version>1.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.4.0</version>
<scope>test</scope>
</dependency>