Surefire无法识别Junit 4测试。

46

由于某种原因,我无法让Maven 2 Surefire插件执行JUnit 4测试类。

public class SimpleTest {
  @org.junit.Test
  public void simple() {
     System.out.println("foo");
  }
}

然而,如果我将这个类更改为类似于JUnit-3的方式,比如:

public class SimpleTest extends junit.framework.TestCase {
  public void testBar() {
     System.out.println("bar");
  }

  @org.junit.Test
  public void simple() {
     System.out.println("foo");
  }
}

然后它就被执行了。下面是我所做的:

  • 确保Maven版本正确:Apache Maven 2.2.1(r801777; 2009-08-06 20:16:01+0100)
  • 确认Surefire插件版本:按照这里的建议进行操作。
  • 确认Surefire插件版本:检查我的~/.m2/repository/org/apache/maven/surefire目录下的Surefire jars——全部都是2.4.2或2.4.3版本。
  • 通过运行mvn dependency:tree | grep junit命令,确保我只依赖于JUnit 4.7版本。

我遇到问题的模块没有使用JUnit 3测试。

我还漏掉了什么吗?


你可以发一下你的 POM 文件吗?那样会更容易些。 - Andreas Dolk
出于法律原因和长度限制,我无法发布完整的POM文件 - 这是一个庞大的项目,仅在POM文件中就有数百行代码。我可能可以发布相关部分,但不确定哪些部分是相关的。 - mindas
1
好的,至少要检查一下maven-surefire-plugin的配置(如果你有一个或者继承了一个)。你能否说一下这个问题是否只出现在一个模块中?它是否发生在项目外部?你是从公司的POM继承的吗? - Pascal Thivent
你能详细说明一下"无法执行"的症状吗? - Kaleb Pederson
13个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
42

mvn -X帮助我揭示了以下内容:

...
[INFO] [surefire:test {execution: default-test}]
[DEBUG] dummy:dummy:jar:1.0 (selected for null)
[DEBUG]   org.apache.maven.surefire:surefire-booter:jar:2.4.3:runtime (selected for runtime)
[DEBUG]     org.apache.maven.surefire:surefire-api:jar:2.4.3:runtime (selected for runtime)
[DEBUG] Adding to surefire booter test classpath: /home/mindas/.m2/repository/org/apache/maven/surefire/surefire-booter/2.4.3/surefire-booter-2.4.3.jar
[DEBUG] Adding to surefire booter test classpath: /home/mindas/.m2/repository/org/apache/maven/surefire/surefire-api/2.4.3/surefire-api-2.4.3.jar
[DEBUG] dummy:dummy:jar:1.0 (selected for null)
[DEBUG]   org.testng:testng:jar:jdk15:5.8:test (selected for test)
[DEBUG]     junit:junit:jar:3.8.1:test (selected for test)
[DEBUG] Adding to surefire booter test classpath: /home/mindas/.m2/repository/org/testng/testng/5.8/testng-5.8-jdk15.jar
[DEBUG] Adding to surefire booter test classpath: /home/mindas/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar
[DEBUG] dummy:dummy:jar:1.0 (selected for null)
[DEBUG] Retrieving parent-POM: org.apache.maven.surefire:surefire-providers:pom:2.4.3 for project: null:surefire-testng:jar:null from the repository.
[DEBUG] Adding managed dependencies for unknown:surefire-testng
[DEBUG]   org.apache.maven.surefire:surefire-api:jar:2.4.3
[DEBUG]   org.apache.maven.surefire:surefire-booter:jar:2.4.3
[DEBUG]   org.codehaus.plexus:plexus-utils:jar:1.5.1
[DEBUG]   org.apache.maven.surefire:surefire-testng:jar:2.4.3:test (selected for test)
[DEBUG]     org.apache.maven:maven-artifact:jar:2.0:test (selected for test)
[DEBUG]       org.codehaus.plexus:plexus-utils:jar:1.0.4:test (selected for test)
[DEBUG]     junit:junit:jar:3.8.1:test (selected for test)
[DEBUG]     org.testng:testng:jar:jdk15:5.7:test (selected for test)
[DEBUG]     org.apache.maven.surefire:surefire-api:jar:2.4.3:test (selected for test)
...
[DEBUG] Test Classpath :
...
[DEBUG]   /home/mindas/.m2/repository/junit/junit/4.7/junit-4.7.jar

看起来问题是由于 testng jar 需要 JUnit v3.8.1 引起的。即使 Test Classpath 被设置为依赖于 JUnit 4,但已经太晚了。

testng 依赖项位于我的 POM 中:

<dependency>
  <groupId>org.testng</groupId>
  <artifactId>testng</artifactId>
  <version>5.8</version>
  <scope>test</scope>
  <classifier>jdk15</classifier>
</dependency>

我将其注释掉后立即开始执行测试。

得到的教训:

  • mvn dependency:tree 并不总是够用,mvn -X 是一个好工具。
  • surefire 不是为开发者量身定制的(我在查看项目 JIRA 报告时意识到这一点)。特别是当你使用Maven时,如果没有其他选择。

感谢大家的帮助。不幸的是,无法在Pascal和Kaleb之间分配答案点数,但是Kaleb建议使用 mvn -X 帮助我走上了正确的轨道,因此正确的答案点数归给了他。


2
实际上,您应该接受自己的答案,因为它提供了解决问题的完整方案 :) - Pascal Thivent

32

Surefire插件根据类路径确定应使用哪个JUnit提供程序。如果类路径上有多个JUnit版本,您可以纠正类路径以使其只有一个JUnit版本(如上所述),或者可以明确指定要使用的提供程序。例如,在父POM中指定以下内容可以强制使用最新的提供程序(例如,“surefire-junit47”):

[...]
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.8</version>
  <dependencies>
    <!-- Force using the latest JUnit 47 provider -->
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <artifactId>surefire-junit47</artifactId>
      <version>2.8</version>
    </dependency>
  </dependencies>
[...]

需要注意的是,Surefire 2.7改变了它确定运行哪些单元测试类的方式。 使用Surefire 2.7(或更高版本)与JUnit 4时的新行为是,任何没有@Test注释的测试都将自动跳过。 如果你只有JUnit 4单元测试,这可能很棒,但如果你同时拥有JUnit 3和4单元测试,则使用"surefire-junit47"提供程序将无法正常工作。在这种情况下,最好明确选择"surefire-junit4"提供程序:

[...]
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.8</version>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven.surefire</groupId>
      <!-- Use the older JUnit 4 provider -->
      <artifactId>surefire-junit4</artifactId>
      <version>2.8</version>
    </dependency>
  </dependencies>
[...]

14

我不知道你所说的“无法执行”是什么意思,但是否明确设置maven-surefire-plugin使用的包可以帮助解决问题?

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.4.3</version>
    <configuration>
        <includes>
            <include>**/*Test.java</include>
        </includes>
    </configuration>
</plugin>

另外,使用 -X 标志运行 Maven 是否提供有用的信息?


谢谢你的提示使用-X,这帮助我揭示了问题(请参见我的答案) - mindas

13

可能还有另一种可能的原因是这个问题(已关闭并标注为“不修复”):https://issues.apache.org/jira/browse/SUREFIRE-587

简短概述:如果测试类继承了TestCase(但没有使用注释),则如果它们的名称不以“Test”结尾,则不会被检测到。


1
不,这对我来说并不是真正的原因(请看我的回答)。不管怎样,感谢你的提示——可能会对其他人有所帮助。 - mindas
是的,我看到了你的解决方案。我也有同样的问题,对我来说解决方案就是这个 bug。这就是为什么我在这里分享它的原因。 - Gábor Lipták
1
谢谢!由于这个“特性”,我花了几个小时进行调试。 - Gal
1
SUREFIRE-587 的最新链接:https://issues.apache.org/jira/browse/SUREFIRE-587 感谢 Gábor 的提示。 - ocroquette

13

如果您的依赖项中有JUnit 5 (import org.junit.jupiter.api.Test;),并且您正在尝试运行一些JUnit4 (import org.junit.Test;)测试,请确保包含以下依赖关系:

<dependency>
  <groupId>org.junit.vintage</groupId>
  <artifactId>junit-vintage-engine</artifactId>
  <scope>test</scope>
</dependency>

注意:我将我的服务从2.3.5.RELEASE升级到2.6.7
  • 添加依赖项junit 4.13.2和junit-vintage-engine
  • Swagger 2更改为使用springdoc-openapi-ui 1.6.8
  • 管理.info.env.enabled=true,适用于路径/info
- Visarut Sae-Pueng
这对我很有帮助。我们有一堆混乱的junit4和5测试。 - TeaCoder

10

对于某些可怜的人来说,他们想知道为什么Maven不会选择JUnit测试。

我有JUnit和TestNG作为依赖项。但是我希望failsafe使用TestNG运行我的功能测试,而surefire使用JUnit运行我的单元测试。

然而,我发现surefire试图使用TestNG运行我的单元测试,并且没有找到任何要运行的内容。我的JUnit测试被跳过了。

后来我遇到了这个Maven问题,并像这样配置surefire只运行“JUnit”测试:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <properties>
      <property>
        <name>junit</name>
        <value>true</value>
      </property>
    </properties>
  </configuration>
</plugin>
希望这能帮助到某人。

1
这个特定的解决方案帮了我很大忙!! - Kushal Paudyal

5
为了方便谷歌员工,当我遇到这个问题时,是因为我包含了一个PowerMock依赖项,它引入了TestNG,导致SureFire没有检测到任何[TestNG]测试。 我使用了m2eclipse“依赖关系”选项卡的POM编辑器来查找依赖关系,并右键单击生成排除(请参见下面的XML)。 为了完整起见(以及对于那些不使用m2eclipse的人),这里是排除依赖关系的XML - 我只是通过看到这些标签自动生成来发现Maven的这个功能:
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-mockito-release-full</artifactId>
  <version>1.4.9</version>
  <classifier>full</classifier>
  <exclusions>
    <exclusion>
      <artifactId>powermock-module-testng</artifactId>
      <groupId>org.powermock</groupId>
    </exclusion>
  </exclusions>
</dependency>
在我的情况下,仅排除“powermock-module-testng”就足够了,但如果它来自其他地方,您也可以直接排除TestNG。

非常感谢您的提示。我遇到了同样的问题,原因是PowerMock。再次感谢您的帮助,如果没有这篇文章,我会在错误的方向上寻找很长时间。 - AHungerArtist

3

1.) 在pom.xml文件中包含以下的Surefire插件

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
</configuration>
</plugin>

2.) 默认情况下,surefire插件从包src/test/java/...中选择测试类。

因此,请在类路径中添加测试文件夹,如下所示:

enter image description here enter image description here

3.) 转到 --> 运行 --> Maven测试

[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.081 
s - in com.bnym.dcm.api.controller.AccountControllerTest
[INFO] Running com.bnym.dcm.api.controller.DCMApiControllerTest
[INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 s - 
in com.bnym.dcm.api.controller.DCMApiControllerTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 7, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ----------------------------------------------------------------------
--
[INFO] BUILD SUCCESS

2

一个小改变让我非常有趣!

我将类名由MyClassTest更改为TestMyClass,这个想法是在验证我的父POM.xml包含以下行之后得到的

<test.include.pattern> **/Test*.java <test.include.pattern/>

1

你所做的验证很好,特别是检查你是否正在使用 2.3+ 版本的 surefire 插件(默认情况下,你会得到 Maven 2.1 的 2.4.3 版本 super POM,所以应该没问题),并检查你没有传递依赖项 junit-3.8.1.jar

现在,只是为了验证这不是一个“全局性问题”(我不这样认为,老实说),你能否从头开始创建一个项目,例如运行:

mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=maven-junit4-testcase

然后更新junit依赖项:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.7</version>
  <scope>test</scope>
</dependency>

并配置编译器级别为1.5+

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>1.5</source>
    <target>1.5</target>
  </configuration>
</plugin>

最后将你的 SimpleTest.java 放在 AppTest.java 旁边,运行 mvn test

如果对该项目运行 mvn test 没有问题(我期望它能够顺利运行),请更新你的问题,附上你所使用的 POM 配置(来自出现问题的项目)。


我按照你的建议去做了,确实执行了AppTest和我的测试。明天会尝试深入挖掘并/或发布相关的POM代码片段。非常感谢Pascal!你的方法也可以在调试相同问题时受益于其他人。顺便问一下,你能修改你的插件mvn代码吗?-你忘记在结尾处关闭插件标签了。 - mindas
调试显示它通过传递方式拉取了junit-3.8.1.jar。我该如何覆盖它? - Akshay Hazari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,