vscode-java-test icon indicating copy to clipboard operation
vscode-java-test copied to clipboard

NoClassDefFoundError for PreconditionViolationException when running JUnit5 tests

Open michalhosala opened this issue 5 years ago • 8 comments

I can no longer run unit tests for my spring app within VSCode IDE, am only getting the following error when trying to do so:

java.lang.NoClassDefFoundError: org/junit/platform/commons/PreconditionViolationException
	at org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader.createTest(JUnit5TestLoader.java:90)
	at org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader.loadTests(JUnit5TestLoader.java:48)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:526)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.lang.ClassNotFoundException: org.junit.platform.commons.PreconditionViolationException
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)

PreconditionViolationException is now deprecated, see here, so it would seem Java Test Runner is not aware of it or what. Currently my build.gradle has junit dependencies like this:

        testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.0"
        testImplementation "org.junit.jupiter:junit-jupiter-params:5.6.0"
        testImplementation "org.springframework.boot:spring-boot-starter-test:2.2.8.RELEASE"
        testRuntime "org.junit.jupiter:junit-jupiter-engine:5.6.0"

I had a look at what seemed like a related issue but none of the workarounds from there worked for me.

michalhosala avatar Jun 24 '20 10:06 michalhosala

Would you mind to share a sample project to us?

Test Runner is not responsible to resolve the classpath so I guess there's something wrong with the upstream side. (Maybe buildship) I need a sample project to repro the issue and then take a look where is the gap

jdneo avatar Jun 28 '20 02:06 jdneo

Hi @jdneo , I can't share my exact project, but I made a stripped down version to reproduce the issue. See here: https://drive.google.com/file/d/1ou7yTyjmeFqmXrkhid0k7DqGP3tJ06-J/view?usp=sharing

Seems like when I remove the following from build.gradle, things start to work, but I have to be on jdk 11:

ext {
    jdkVersion = "11"
}

Thanks for having a look!

michalhosala avatar Jun 29 '20 13:06 michalhosala

Please try the following configurations:

dependencies {
    implementation "org.springframework.boot:spring-boot-starter-jetty:2.1.5.RELEASE"
    implementation "org.springframework.boot:spring-boot-starter-thymeleaf:2.1.5.RELEASE"
    implementation ("org.springframework.boot:spring-boot-starter-web:2.1.5.RELEASE") {
        exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
    }
    runtimeOnly "org.springframework.boot:spring-boot-devtools:2.1.5.RELEASE"
    testImplementation "org.hamcrest:hamcrest-library:2.1"
    testImplementation "org.junit.jupiter:junit-jupiter:5.6.0"
    testImplementation "org.springframework.boot:spring-boot-starter-test:2.1.5.RELEASE"
    compile "org.junit.platform:junit-platform-commons:1.6.0"
    testCompile "org.junit.platform:junit-platform-engine:1.6.0"
}

jdneo avatar Jul 01 '20 06:07 jdneo

@jdneo your workaround enabled me to run the tests in VS code. Any idea where is the actual problem and how to address it?

michalhosala avatar Jul 02 '20 14:07 michalhosala

Hmm, I guess too soon. When I applied this remedy to my original project, not just a demo, it started throwing another error, again related to preconditions:

java.lang.IllegalArgumentException: Error: test loader org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader not found:
org.junit.platform.commons.PreconditionViolationException: Cannot create Launcher without at least one TestEngine; consider adding an engine implementation JAR to the classpath
	at org.junit.platform.commons.util.Preconditions.condition(Preconditions.java:296)
	at org.junit.platform.launcher.core.DefaultLauncher.<init>(DefaultLauncher.java:62)
	at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:91)
	at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:67)
	at org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader.<init>(JUnit5TestLoader.java:34)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.base/java.lang.Class.newInstance(Class.java:584)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createRawTestLoader(RemoteTestRunner.java:371)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createLoader(RemoteTestRunner.java:366)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.defaultInit(RemoteTestRunner.java:310)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.init(RemoteTestRunner.java:225)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createRawTestLoader(RemoteTestRunner.java:376)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createLoader(RemoteTestRunner.java:366)
java.lang.IllegalArgumentException: Error: test loader org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader not found:
org.junit.platform.commons.PreconditionViolationException: Cannot create Launcher without at least one TestEngine; consider adding an engine implementation JAR to the classpath
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.defaultInit(RemoteTestRunner.java:310)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.init(RemoteTestRunner.java:225)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

It went away after I put the following dependency back as well:

testRuntime "org.junit.jupiter:junit-jupiter-engine:5.3.2"

michalhosala avatar Jul 02 '20 16:07 michalhosala

I guess all of the problem is about the classpath. What I did is find where the missing class comes from and add them into the dependecies.

Could I understand the problem has been solved now?

jdneo avatar Jul 03 '20 08:07 jdneo

@jdneo but the problem was not present before vs code update / extension update,on top of that the code is working fine outside of the VS code, in intelliJ, from command line etc. So the problem is not "solved" for VS code, just "worked around". As I already wrote in my first comment, "PreconditionViolationException is now deprecated" so I don't think correct solution is to try and patch the missing classes but rather accommodate for the class being deprecated.

michalhosala avatar Jul 03 '20 08:07 michalhosala

@michalhosala I got this too but problem is in junit jupiter, some libs absent and testImplementation "org.junit.jupiter:junit-jupiter:5.6.0" fix it. Because it contains all libs. But second error is about testImplementation "org.junit.jupiter:junit-jupiter-engine:5.6.0" which is not exist too. Just add it.

pumano avatar Apr 10 '21 19:04 pumano