使用 spring boot gradle 插件无法使用依赖管理执行 junit5 测试

Posted

技术标签:

【中文标题】使用 spring boot gradle 插件无法使用依赖管理执行 junit5 测试【英文标题】:Failed to execute junit5 tests with dependency management with spring boot gradle plugin 【发布时间】:2019-10-26 22:46:05 【问题描述】:

在我基于 gradle 和 kotlin 的项目中,我有一些子模块。为 it 模块构建配置(build.gradle.kts):

plugins 
    java
    kotlin("jvm")
    id("org.springframework.boot") version "2.1.5.RELEASE"
    id("io.spring.dependency-management") version "1.0.7.RELEASE"


dependencies 

    compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.31")
    compile("org.springframework.boot:spring-boot-starter-web")

    testCompile("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.31")
    testCompile("org.jetbrains.kotlin:kotlin-stdlib:1.3.31")
    testCompile("org.jetbrains.kotlin:kotlin-reflect:1.3.31")

    testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.2")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.4.2")

我尝试在这个模块中运行一些简单的测试

简单类:

class Hello 
    fun hello(): String 
        return "hello"
    

简单测试:

class HelloTest 
    @Test
    fun test() 
        Assertions.assertEquals(Hello().hello(), "hello")
    

当我尝试运行测试时出现错误:

Jun 12, 2019 2:58:31 PM org.junit.platform.launcher.core.DefaultLauncher handleThrowable
WARNING: TestEngine with ID 'junit-jupiter' failed to execute tests
java.lang.NoSuchMethodError: org.junit.platform.commons.util.ReflectionUtils.tryToLoadClass(Ljava/lang/String;)Lorg/junit/platform/commons/function/Try;
    at org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector.createAbortedExecutionPredicate(OpenTest4JAndJUnit4AwareThrowableCollector.java:40)
    at org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector.<clinit>(OpenTest4JAndJUnit4AwareThrowableCollector.java:30)
    at org.junit.jupiter.engine.support.JupiterThrowableCollectorFactory.createThrowableCollector(JupiterThrowableCollectorFactory.java:34)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:68)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:102)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:82)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:78)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:175)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:157)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    at java.lang.Thread.run(Thread.java:748)

FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:rest:test'.
> No tests found for given includes: [ua.company.app.Hello](filter.includeTestsMatching)
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1s
4 actionable tasks: 2 executed, 2 up-to-date
No tests found for given includes: [ua.company.app.Hello](filter.includeTestsMatching)

但是如果从我的构建配置中删除 id("io.spring.dependency-management") version "1.0.7.RELEASE" 并且将使用这样的 spring boot 版本 compile ("org.springframework.boot:spring-boot-starter-web:2.1.5.RELEASE") 测试运行正常。

Spring 依赖管理破坏了我的 junit5 测试。请任何人解释为什么会发生这种情况以及如何解决这个问题?谢谢!

【问题讨论】:

什么是io.spring.dependency-management? github.com/spring-gradle-plugins/dependency-management-plugin 和指导docs.spring.io/spring-boot/docs/2.0.0.RELEASE/gradle-plugin/… 哦,我明白了。我不使用 Gradle,但我知道 Sam Brannen 正在研究 JUnit5 集成。看看这里:github.com/sbrannen/junit5-demo希望这可能会有所帮助 Gradle 5 JUnit BOM and Spring Boot Incorrect Versions的可能重复 【参考方案1】:

似乎添加 Spring 依赖管理会更改您的 junit-jupiter 依赖项的一些传递依赖项。

您声明的 junit 版本 (5.4.2) 依赖于 junit-platform-commons 1.4.2,但是当您添加 Spring 依赖管理时,它会将 commons 版本从 1.4.2 更改为 1.3.2。这就是您收到 NoSuchMethodError 的原因,因为该方法是在第四版中添加的!

这是我能想到的两个解决方案:

1)(我推荐这个)删除你声明的 junit 版本,让 Spring Dependency Management 处理 junit 的所有内容:

testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntime("org.junit.jupiter:junit-jupiter-engine")

2) 声明 junit 的传递依赖版本(如果这是必须的,这将允许您继续使用版本 5.4.2)

testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.2")
testImplementation("org.junit.platform:junit-platform-commons:1.4.2")
testRuntime("org.junit.jupiter:junit-jupiter-engine:5.4.2")
testRuntime("org.junit.platform:junit-platform-engine:1.4.2")

【讨论】:

以上是关于使用 spring boot gradle 插件无法使用依赖管理执行 junit5 测试的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 spring-boot gradle 插件进行 proguard

多模块 Spring Boot 项目中的 Gradle 依赖插件

Spring Boot Gradle 插件凭据

Spring Boot gradle 插件强制 Mockito 版本

如何使用 Spring Boot“bootJar”插件创建 gradle 任务以生成爆炸性战争?

使用 spring boot gradle 插件无法使用依赖管理执行 junit5 测试