Maven/Surefire 无法在同一项目中执行 Spock 和 JUnit

Maven/Surefire can't execute Spock and JUnit in the same project

环境

$ java -version
java version "1.8.0_241"
Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode)
$ mvn -version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.3\plugins\maven\lib\maven3
Java version: 1.8.0_231, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk1.8.0_231\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

问题

我分叉了spockframework/spock-example add java test directory and HelloJUnitTest.java => sunzy/spock-exmaple

Spock 测试可以执行,但 JUnit 测试不能

快照

只有 spock 测试!

好的,我已经看过你的项目了。如您所说,它只是 Spock 示例项目,已升级为 运行 Spock 2 测试。 顺便说一句,它仍然应该进一步升级,因为在当前配置中编译不适用于当前 Java 版本,但这不是主题,我只是提到它因为我 运行 进入问题然后降级为 Java 8 以便快速重现您的实际问题。 JUnit 测试的包名称也不是问题,即使默认包总是丑陋的,就像 for Spock 测试。

Spock 1.x 基于 JUnit 4,但 Spock 2.x 基于 JUnit 5 平台。这也是Surefire在分析项目依赖时自动找到的。如果想让Surefire运行多个引擎并行,需要将相应的provider配置为插件依赖,如here.

所述

对于您的情况,只需将其添加到 POM 中:

  <plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M4</version>
    <configuration>
      <useFile>false</useFile>
      <includes>
        <include>**/*Test.java</include>
        <include>**/*Spec.java</include>
      </includes>
    </configuration>

    <!-- Run Spock 2 and JUnit 4 tests in parallel -->
    <dependencies>
      <dependency>
        <groupId>org.apache.maven.surefire</groupId>
        <artifactId>surefire-junit47</artifactId>
        <version>3.0.0-M4</version>
      </dependency>
      <dependency>
        <groupId>org.apache.maven.surefire</groupId>
        <artifactId>surefire-junit-platform</artifactId>
        <version>3.0.0-M4</version>
      </dependency>
    </dependencies>

  </plugin>

将 JUnit 4.12 或 4.13 的测试范围依赖项显式添加到您的 POM 也是有意义的,因为 JUnit 4.12 在您当前的 POM 中只是一个 t运行sitive 依赖项。但后来的 Spock 2 版本可能会删除该依赖项,因为它并不是真正需要的。我认为 2.0-M3 已经发生了。所以要小心。

此更改后,Maven 说:

[INFO] --- maven-surefire-plugin:3.0.0-M4:test (default-test) @ spock-example ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running HelloJUnitTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.059 s - in HelloJUnitTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running DatabaseDrivenSpec
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.171 s - in DatabaseDrivenSpec
(...)
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 39, Failures: 0, Errors: 0, Skipped: 0

如果您决定从 JUnit 4 升级到 5,配置对您来说可能会更容易,因为 Spock 和 JUnit 使用相同的提供程序。在这种情况下,请添加 JUnit 5 依赖项,以便您的测试可以导入相应的测试注释和断言方法。


更新: 在@khmarbaise 评论使用老式引擎并且我完全同意这是更好的解决方案之后,我想向您展示如何做到这一点而不是添加插件依赖项到万无一失。 (所以如果你想使用这个解决方案,你可以删除那些):

<dependency> <!-- only required if you want to run JUnit 4 tests alongside Spock 2 -->
  <groupId>org.junit.vintage</groupId>
  <artifactId>junit-vintage-engine</artifactId>
  <version>5.5.2</version>
  <scope>test</scope>
</dependency>

为什么是 5.5.2 版本而不是例如5.6.2?为了避免版本冲突和随后关于 vintage engine not finding tests in the Groovy directory 的警告。这是因为此示例项目中的 POM 仍然使用 Spock 2.0-M1 BOM。正如我所说,它应该更新。但是对于这个版本,它可以正常工作,因为它依赖于与此配置中的 Spock 相同的 JUnit 5 平台版本。

顺便说一句,现在 Maven 先执行 Spock 测试,然后执行 JUnit 4 测试,因此两者的日志输出顺序会相反。