JUnit5:Surefire 插件运行 JUnit4 测试两次

JUnit5: Surefire plugin runs JUnit4 tests twice

我的项目中有 JUnit4 和 JUnit5 测试。问题是当我 运行 mvn clean install 时,JUnit4 测试是 运行 两次(JUnit5 测试 运行 很好,只有一次)。

我的父项目 pom

中有以下 surefire-plugin 配置(仅显示相关依赖项)
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.22.2</version>
  <configuration>
    <threadCount>1</threadCount>
    <properties>
      <property>
        <name>junit</name>
        <value>false</value>
      </property>
    </properties>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-testng</artifactId>
      <version>2.22.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-junit-platform</artifactId>
      <version>2.22.2</version>
    </dependency>
  </dependencies>
</plugin>
...
...
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-engine</artifactId>
  <version>5.6.2</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.junit.vintage</groupId>
  <artifactId>junit-vintage-engine</artifactId>
  <version>5.6.2</version>
  <scope>test</scope>
</dependency>
<dependency>
  <!-- needed for https://youtrack.jetbrains.com/issue/IDEA-231927?_ga=2.101965186.223349104.1602977709-1646014256.1600106493 -->
  <groupId>org.junit.platform</groupId>
  <artifactId>junit-platform-launcher</artifactId>
  <version>1.6.2</version>
  <scope>test</scope>
</dependency>

我也在子项目中复制了上面的 surefire-plugin,以确保它不会被任何东西覆盖。但是,JUnit4 测试仍然是 运行 两次。

以下是有效pom中的surefire-plugin部分-

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.22.2</version>
  <configuration>
    <threadCount>1</threadCount>
    <properties>
      <property>
        <name>junit</name>
        <value>false</value>
      </property>
    </properties>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-testng</artifactId>
      <version>2.22.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-junit-platform</artifactId>
      <version>2.22.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-junit47</artifactId>
      <version>2.19.1</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</plugin

在使用 -X 选项进行一些调试时,我认为原因是因为 surefire-junit47 也被添加到 surefire-plugin 的提供程序中,surefire-junit-platform 运行s junit4 测试一次,surefire-junit47 供应商再次 运行。如果这是一个可能的原因,那么我怎样才能防止它被添加到 surefire-plugin 依赖项中?我试过 <classpathDependencyExcludes> 但这没有帮助,有效的 pom 仍然包含 surefire-junit47。

即使同时拥有两个提供程序(surefire-junit47surefire-junit-platform),还有什么方法可以避免 JUnit4 运行ning 两次?

------------更新------------

我还在配置中将 junit 属性 设置为 false 以防止 testng 提供程序 运行 进行 junit 测试(建议 here).但是,我仍然得到了两个 运行 的 JUnit4 测试。我的猜测是不知何故 surefire-junit47(神秘地添加)和 surefire-junit-platform 在一起表现得很奇怪导致重复的 运行s.

------------更新------------

实际问题是我的项目继承了一个父pom,它在surefire-plugin中声明了一个依赖surefire-junit47。如此有效,我的项目同时具有 surefire-junit-platform 和 surefire-junit47,这导致双重 运行s 的 JUnit4 测试。

我能够重现您的问题。您正在 运行 陷入 here:

描述的情况

TestNG 6.5.1 and higher provides support to run TestNG and JUnit 4.x in current Maven project. (...)

You may want to run two providers, e.g. surefire-junit47 and surefire-testng, and avoid running JUnit tests within surefire-testng provider by setting property junit=false.

所以请将您的 Surefire 插件配置更改为:

<configuration>
  <threadCount>1</threadCount>
  <properties>
    <!-- Avoid running JUnit 4 tests in TestNG engine -->
    <property>
      <name>junit</name>
      <value>false</value>
    </property>
  </properties>
</configuration>

更新:如何(伪)排除直接的 Maven 插件依赖:

好吧,FWIW 我想出了一个 hacky 方法来“排除”依赖项,方法是用一个虚拟对象覆盖它。

首先,您将一个模块添加到项目的根 POM,但没有指定根 POM 作为其父级。只需确保模块构建在同一个反应器中即可。或者,您也可以为其创建一个单独的项目,并确保其生成的工件在您公司的存储库中。

模块 POM 如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.apache.maven.surefire</groupId>
  <artifactId>surefire-junit47</artifactId>
  <version>dummy</version>
</project>

在您希望停用 JUnit 4.7 引擎以支持 运行在 JUnit 5 平台上进行 JUnit 4 测试的子 POM 中,您可以执行如下操作:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>${maven-surefire.version}</version>
  <configuration>
    <threadCount>1</threadCount>
    <properties>
      <!-- Avoid running JUnit 4 tests in TestNG engine -->
      <property>
        <name>junit</name>
        <value>false</value>
      </property>
    </properties>
  </configuration>
  <dependencies>
    <dependency>
      <!-- Deactivate JUnit 4.7 engine by overriding it with an empty dummy -->
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-junit47</artifactId>
      <version>dummy</version>
    </dependency>
  </dependencies>
</plugin>

<!-- (...) -->

<dependencies>
  <dependency>
    <groupId>org.apache.maven.surefire</groupId>
    <artifactId>surefire-junit47</artifactId>
    <version>dummy</version>
  </dependency>
</dependencies>

这太丑陋了,如果可能的话,我仍然建议重构父 POM。无论如何,它有效。现在,您的 JUnit 4 测试仅 运行 一次,即在 JUnit 5 平台内与 JUnit 5 测试、Spock 2.0 测试或您拥有的测试一起进行。


更新 2: 在您提供 MCVE on GitHub, I sent you a pull request implementing exactly the workaround I mentioned in the previous update. The important commit is this one.