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-junit47
和 surefire-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.
我的项目中有 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-junit47
和 surefire-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
andsurefire-testng
, and avoid running JUnit tests withinsurefire-testng
provider by setting propertyjunit=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.