我在 Eclipse 中有一个简单的 Java 11 项目,具有以下依赖项:
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:${junit}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junit}")
}
项目结构如下:
module-info.java仅导出模块 simple.tests 中的包simple.tests。
我已经定义了以下 Gradle 任务来正确设置 Eclipse 项目及其依赖项。测试依赖项位于类路径上,这些仅对测试源可见。
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'
}
}
}
}
我可以使用以下设置在 Gradle (5.0) 中编译和运行测试用例:
test {
useJUnitPlatform()
}
ext.moduleName = 'simple.tests'
compileJava {
inputs.property("moduleName", moduleName)
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
]
classpath = files()
}
}
但是,我无法在 Eclipse 中执行 JUnit 测试,因为我收到一条错误消息(没有使用测试运行器“Junit 5”找到测试)和以下堆栈跟踪:
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)
将测试依赖项移动到模块路径并不能解决问题。在这种情况下,即使在将 Junit Launcher 添加到模块路径之后,我也会得到以下堆栈跟踪:
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
我找到的唯一解决方案是删除 module-info.java 文件。删除模块描述符后,测试用例可以在 Eclipse 和 Gradle 中执行。
我的配置中有错误的设置吗?还是我做错了什么?
先感谢您!