4

I have a simple Java 11 project in Eclipse with the following dependencies:

dependencies {   
    testImplementation("org.junit.jupiter:junit-jupiter-api:${junit}")  
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junit}")
}

The project structure is as follows:

project structure

The module-info.java only exports the package simple.tests in the module simple.tests.

I have defined the following Gradle tasks for setting up the Eclipse project and its dependencies properly. The test dependencies are on the classpath and these are only visible to the test sources.

eclipse {
    classpath {
        file {
            whenMerged {
                entries.findAll { 
                    it.kind == 'src' || it.kind == 'lib' 
                }.each { it.entryAttributes['module'] = 'true' }
            }
        }
    }
}

eclipse.classpath.file.whenMerged {

    // Setting output folder for main files
    def mainSrc = entries.find { it.path == 'src/main/java' }
    if(mainSrc != null) {
        mainSrc.output = 'bin/main'
    }

    def mainResources = entries.find { it.path == 'src/main/resources' }
    if(mainResources != null) {
        mainResources.output = 'bin/main'
    }

    // Setting output folder for test files
    def testSrc = entries.find { it.path == 'src/test/java' }
    if(testSrc != null) {
        testSrc.output = 'bin/test'
        testSrc.entryAttributes['test'] = 'true'
        testSrc.entryAttributes['module'] = 'false'
    }

    def testResources = entries.find { it.path == 'src/test/resources' }
    if (testResources != null) {   
        testResources.output = 'bin/test'
        testResources.entryAttributes['test'] = 'true'
        testResources.entryAttributes['module'] = 'false'
    }

    // Updating test dependencies' visibility and adding them to module path
    // instead of the classpath
    entries.forEach { entry ->
        def entryIn = { it.find { file(entry.path).equals(it) } }
        if (entry.kind == 'lib') {
            entry.entryAttributes['test'] =
               entryIn(configurations.testRuntimeClasspath) &&
                !entryIn(configurations.runtimeClasspath)
            if(entry.entryAttributes['test']) {
                entry.entryAttributes['module'] = 'false'
           }
        }
    }
}

I am able to compile and run the test cases in Gradle (5.0) with the following settings:

test {
     useJUnitPlatform()
}

ext.moduleName = 'simple.tests' 

compileJava {
    inputs.property("moduleName", moduleName)
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,
        ]
        classpath = files()  
    }
}

However, I can not execute the JUnit test in Eclipse because I get the an error message (No tests found with test runner 'Junit 5') and the following Stack Trace:

Class not found simple.tests.DummyTest
java.lang.ClassNotFoundException: simple.tests.DummyTest
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.loadClass(RemoteTestRunner.java:773)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.loadClasses(RemoteTestRunner.java:502)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:525)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

Moving the test dependencies to the module path doesn't solve the problem. In this case I get the following Stack Trace, even after adding Junit Launcher to the module path:

java.lang.NoClassDefFoundError: org/junit/platform/engine/EngineExecutionListener
    at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:59)
    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:370)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createLoader(RemoteTestRunner.java:365)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.defaultInit(RemoteTestRunner.java:309)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.init(RemoteTestRunner.java:224)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:208)
Caused by: java.lang.ClassNotFoundException: org.junit.platform.engine.EngineExecutionListener
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    ... 12 more

The only solution I found was removing the module-info.java file. After deleting the module descriptor, the test case(s) can be executed in Eclipse and in Gradle as well.

Is there a wrong setting in my configuration? Or am I doing anything wrong?

Thank you in advance!

l_mcqueen
  • 55
  • 6
  • did you find any solution? I'd like to know more Gradle + Eclipse + java module is really a pain imho. – RegRog Mar 26 '20 at 22:09
  • no, sadly, I didn't find any solution – l_mcqueen Mar 27 '20 at 07:35
  • Wait for this! Hope will fix all these problems. https://github.com/gradle/gradle/issues/890#issuecomment-603289940 – RegRog Mar 27 '20 at 12:29
  • Thank you for your response. I don't work on that project any more, so I won't be able to verify if the new feature solves the problem, but it might be useful for others. – l_mcqueen Apr 06 '20 at 12:59

0 Answers0