Can't run JUnit 5 tests on Eclipse 2021-03

Viewed 2862

I am working on a project that includes both Gradle and Maven subprojects. Until yesterday I was using Eclipse 2020-03, but I updated to 2021-03 and now I can't run any tests. I haven't changed anything to the project's configuration, junit 5.6.0 is included both in pom.xml and build.gradle.

Now whenever I try to run a test, I get this error:

java.lang.NoClassDefFoundError: org/junit/platform/commons/util/ClassNamePatternFilterUtils
at org.junit.platform.launcher.core.LauncherFactory.loadAndFilterTestExecutionListeners(LauncherFactory.java:122)
at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:108)
at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:75)
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)
Caused by: java.lang.ClassNotFoundException: org.junit.platform.commons.util.ClassNamePatternFilterUtils
    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:521)
    ... 14 more

When I add Junit 5 manually to the project's build path, as suggested by a lot of similar questions here, I get this in the Add Library Window:

Current Location: org.junit.jupiter.api_5.7.1.v20210222-1948.jar - /Users/user/.p2/pool/plugins 

But even then, when I add it, I get that junit launcher was not found, followed by:

java.lang.SecurityException: class "org.junit.platform.commons.util.ClassNamePatternFilterUtils"'s signer information does not match signer information of other classes in the same package

Note that in 2020-03, the project's build path did not include explicitly Junit 5 (hadn't added it manually). The same tests also work there as intended, both in Maven and Gradle projects.

I have also tried deleting anything related to the previous eclipse installations (~/Library related contents)

My .classpath is the following:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" output="bin/main" path="src/main/java">
        <attributes>
            <attribute name="gradle_scope" value="main"/>
            <attribute name="gradle_used_by_scope" value="main,test"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="src" output="bin/main" path="src/main/resources">
        <attributes>
            <attribute name="gradle_scope" value="main"/>
            <attribute name="gradle_used_by_scope" value="main,test"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="src" output="bin/test" path="src/test/java">
        <attributes>
            <attribute name="gradle_scope" value="test"/>
            <attribute name="gradle_used_by_scope" value="test"/>
            <attribute name="test" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="src" output="bin/test" path="src/test/resources">
        <attributes>
            <attribute name="gradle_scope" value="test"/>
            <attribute name="gradle_used_by_scope" value="test"/>
            <attribute name="test" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"/>
    <classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
    <classpathentry combineaccessrules="false" kind="src" path="/com.myproject.businesslayer"/>
    <classpathentry kind="output" path="bin/default"/>
</classpath>

The relevant part of my root pom.xml :

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <tycho-version>1.7.0</tycho-version>
        <mockito-version>3.3.0</mockito-version>
        <hamcrest-version>2.1</hamcrest-version>
        <archunit-version>0.11.0</archunit-version>
        <junit-version>5.6.0</junit-version>
        <xmlunit-version>2.6.3</xmlunit-version>

        <!-- plugin versions -->
        <compiler-plugin-version>3.8.0</compiler-plugin-version>
        <groovy-eclipse-compiler-version>3.4.0-01</groovy-eclipse-compiler-version>
        <jar-plugin-version>3.1.2</jar-plugin-version>
        <surefire-plugin-version>2.22.2</surefire-plugin-version>
        <versions-plugin-version>2.7</versions-plugin-version>
        <jacoco-plugin-version>0.8.4</jacoco-plugin-version>
        <sonar-plugin-version>3.8</sonar-plugin-version>
        <groovy-eclipse-batch-version>2.5.8-01</groovy-eclipse-batch-version>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    </properties>
    <modules>
        ...
    </modules>

    <build>
        <defaultGoal>verify</defaultGoal>
        <!-- only relevant for modules containing plain java tests -->
        <sourceDirectory>src</sourceDirectory>
        <testSourceDirectory>test</testSourceDirectory>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>${surefire-plugin-version}</version>
                    <dependencies>
                        <dependency>
                            <groupId>org.junit.jupiter</groupId>
                            <artifactId>junit-jupiter-engine</artifactId>
                            <version>${junit-version}</version>
                        </dependency>
                    </dependencies>
                    <executions>
                        <execution>
                            <id>test</id>
                            <phase>test</phase>
                            <configuration>
                                <includes>
                                    <include>**/*.java</include>
                                </includes>
                                <excludedGroups>PluginTest</excludedGroups>
                            </configuration>
                            <goals>
                                <goal>test</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <!-- only for plain java test execution -->
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>${junit-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.tngtech.archunit</groupId>
            <artifactId>archunit-junit5-api</artifactId>
            <version>${archunit-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.tngtech.archunit</groupId>
            <artifactId>archunit-junit5-engine</artifactId>
            <version>${archunit-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>${mockito-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>${hamcrest-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-library</artifactId>
            <version>${hamcrest-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>${org.assertj}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

and of my root build.gradle:

plugins {
...
}

subprojects { sub ->

    apply plugin: 'java'

    sourceCompatibility = 11
    targetCompatibility = 11
    
    tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
    }
    
    tasks.withType(Test) {
      ...
   }

    dependencies {
        testCompile "org.assertj:assertj-core:${assertJVersion}"
        testCompile "org.junit.jupiter:junit-jupiter-api:${jUnitVersion}"
        testRuntime "org.junit.jupiter:junit-jupiter-engine:${jUnitVersion}"
        testCompile "org.junit.jupiter:junit-jupiter-params:${jUnitVersion}"

        testCompile "org.mockito:mockito-core:${mockitoVersion}"
        testCompile "org.hamcrest:hamcrest:${hamcrestVersion}"
        testCompile "org.slf4j:slf4j-simple:${slf4jVersion}"

        testCompile "com.tngtech.archunit:archunit-junit5-api:${archUnitVersion}"
        testRuntime "com.tngtech.archunit:archunit-junit5-engine:${archUnitVersion}"
    }

    test {
        useJUnitPlatform()
        finalizedBy jacocoTestReport
    }
    
    jacocoTestReport {
        dependsOn test
    }

    repositories {
        mavenLocal()
        jcenter()
        maven {
            url "${nexusUrl}"
        }
    }
}

wrapper {
    gradleVersion = '5.6'
}

and in gradle.properties:

hamcrestVersion=2.1
jUnitVersion=5.6.0
archUnitVersion=0.11.0
2 Answers

The problem is solved if I update the JUnit version both for Maven and Gradle to 5.7.1.

This still does not answer the question why it was working on older Eclipse installations, of course.

In my case i had to remove dependencies from my projects pom.xml that are already comming from a commons library, too. The dependency hierarchy tab in the pom.xml viewer can help very much to detect such problems.

Before: enter image description here

After: enter image description here

Related