【问题标题】:How to run both JUnit5 plus Spock 2.0 tests in Gradle project如何在 Gradle 项目中同时运行 JUnit5 和 Spock 2.0 测试
【发布时间】:2020-11-10 18:56:55
【问题描述】:

我有一个简单的项目,我希望能够同时运行 JUnit 5 单元测试和 Spock 2 功能测试。如果我在下面的 build.gradle 中注释掉了 Spock 依赖项,我的 JUnit5 测试就会运行并通过。但是,如果我取消注释 Spock 依赖项以准备添加 Spock 测试,则 JUnit5 测试开始失败。

我的 build.gradle:

buildscript {
    repositories {
        maven { url "https://plugins.gradle.org/m2/" }
    }
    dependencies {
        classpath(
          "org.springframework.boot:spring-boot-gradle-plugin:2.1.6.RELEASE",
          'net.researchgate:gradle-release:2.8.0'
          )
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'net.researchgate.release'
apply plugin: 'groovy'

repositories {
    mavenCentral()
    jcenter()
}

sourceCompatibility = 11
targetCompatibility = 11

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
    testImplementation 'org.codehaus.groovy:groovy:3.0.5'
    testImplementation group: 'org.spockframework', name: 'spock-spring', version: '2.0-M3-groovy-3.0'
    testImplementation group: 'org.spockframework', name: 'spock-core', version: '2.0-M3-groovy-3.0'
    //testImplementation group: 'org.spockframework', name: 'spock-junit4', version: '2.0-M3-groovy-3.0'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1'
}

test {
    useJUnitPlatform()
}

jar {
   enabled = true
}

bootJar {
    archiveFileName = "app.jar"
}

如果我取消注释 Spock 依赖项会出现错误:

org.gradle.api.internal.tasks.testing.TestSuiteExecutionException: Could not complete execution for Gradle Test Executor 3.
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.util.ServiceConfigurationError: org.junit.platform.engine.TestEngine: org.spockframework.runtime.SpockEngine Unable to get public no-arg constructor
    at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:581)
    at java.base/java.util.ServiceLoader.getConstructor(ServiceLoader.java:672)
    at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1232)
    at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1264)
    at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1299)
    at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1384)
    at java.base/java.lang.Iterable.forEach(Iterable.java:74)
    at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:87)
    at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:67)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:97)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    ... 25 more
Caused by: java.lang.NoClassDefFoundError: org/junit/platform/engine/support/discovery/SelectorResolver
    at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3137)
    at java.base/java.lang.Class.getConstructor0(Class.java:3342)
    at java.base/java.lang.Class.getConstructor(Class.java:2151)
    at java.base/java.util.ServiceLoader$1.run(ServiceLoader.java:659)
    at java.base/java.util.ServiceLoader$1.run(ServiceLoader.java:656)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.util.ServiceLoader.getConstructor(ServiceLoader.java:667)
    ... 36 more
Caused by: java.lang.ClassNotFoundException: org.junit.platform.engine.support.discovery.SelectorResolver
    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)
    ... 44 more

【问题讨论】:

  • 试用 JUnit 5.7.0 或更高版本。

标签: gradle spock junit5


【解决方案1】:

我在这里创建了一个 base_app:https://github.com/robevansuk/base_app/blob/master/build.gradle

group 'com.example'
version '1.0'

apply plugin: 'groovy'
apply plugin: 'java'

sourceCompatibility = 1.8

test { useJUnitPlatform() }

repositories {
  mavenCentral()
}

dependencies {
  implementation 'org.codehaus.groovy:groovy-all:3.0.6'
  implementation 'org.springframework:spring-context:5.3.1'

  testImplementation 'org.junit.jupiter:junit-jupiter:5.7.0'
  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
  testImplementation 'org.spockframework:spock-core:2.0-M4-groovy-3.0'
}

sourceSets {
  main {
    groovy {
      srcDirs = ['src/main/java', 'src/main/groovy']
    }
    resources {
      srcDirs = ['src/main/resources']
    }
  }
}

当我将所有内容都升级到最新版本时,我收到一条错误消息,警告我版本不兼容。访问的结果页面包含下表,但格式不正确。所以我将它们格式化为更具可读性,并将它们包含在下面:

| Spock version | Groovy version | JUnit version | Grails version | Spring version |
|:--------------|:---------------|:--------------|:---------------|:---------------|
| 0.5-groovy-1.6 | 1.6.1-1.6.x | 4.7-4.x | 1.2.0-1.2.x | 2.5.0-3.x |
| 0.5-groovy-1.7 | 1.7.0-1.7.x | 4.7-4.x | 1.3.0-1.3.x | 2.5.0-3.x |
| 0.6-groovy-1.7 | 1.7.0-1.7.x | 4.7-4.x | 1.3.0-1.3.x | 2.5.0-3.x |
| 0.6-groovy-1.8 | 1.8.1-1.8.x | 4.7-4.x | 2.0-2.x | 2.5.0-3.x |
| 0.7-groovy-1.8 | 1.8.1-1.8.x | 4.7-4.x | 2.0-2.x | 2.5.0-3.x |
| 0.7-groovy-2.0 | 2.0.0 -2.x.x | 4.7-4.x | 2.2-2.x | 2.5.0-3.x |
| 1.0-groovy-2.0 | 2.0.0 -2.2.x | 4.7-4.x | 2.2-2.x | 2.5.0-4.x |
| 1.0-groovy-2.3 | 2.3.0 -2.3.x | 4.7-4.x | 2.2-2.x | 2.5.0-4.x |
| 1.0-groovy-2.4 | 2.4.0 -2.x.x | 4.7-4.x | 2.2-2.x | 2.5.0-4.x |

| Spock version | Groovy version | JUnit version | Grails version | Spring version |
|:--------------|:---------------|:--------------|:---------------|:---------------|
| 1.1-groovy-2.0-SNAPSHOT | 2.0.0 -2.2.x | 4.7-4.x | 2.2-2.x | 2.5.0-4.x |
| 1.1-groovy-2.3-SNAPSHOT | 2.3.0 -2.3.x | 4.7-4.x | 2.2-2.x | 2.5.0-4.x |
| 1.1-groovy-2.4-SNAPSHOT | 2.4.0 -2.x.x | 4.7-4.x | 2.2-2.x | 2.5.0-4.x |

【讨论】:

  • 这使用了一个相当旧的 spock 版本,请查看github.com/spockframework/spock-example
  • 而且它根本没有使用 JUnit 5。
  • 我以为你可以管理版本的颠簸,但是我已经更新了答案,为你包括了这个,并把更新推送到我的 repo 中。 Groovy/Spock/Junit 之间存在一些版本依赖关系,因此即使我提供了可用的版本,它们也可能与您所拥有的不兼容。
  • 你的测试真的运行了吗?我在这里的示例中没有看到 test { useJUnitPlatform() },这是 Spock 2.x 所必需的
  • 你确实是正确的 - 我已经将它添加到脚本中,它现在可以从 gradle 成功运行测试
【解决方案2】:

我最终同时使用了新旧 JUnit 引擎:

test.useJUnitPlatform() {
        includeEngines 'junit-vintage'
        includeEngines 'junit-jupiter'
    }

,其中vintage 用于 Spock,jupiter 用于 JUnit5。

这可能不是最好的解决方案,但它确实有效:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-19
    • 2020-01-29
    • 1970-01-01
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多