在 Maven 中运行单个类时正确包含 jUnit5 @Nested 类

Joc*_*ckX 3 java maven maven-surefire-plugin junit5

在 JUnit 5 中执行的类@Nested被命令在封闭类中的所有测试之后运行。如果我的目标是运行单个封闭类及其嵌套类,我如何使用 Maven 强制执行相同的行为?是否有命令行或 pom.xml 修改以使此示例测试通过?

package example;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

public class SomeTopLevelTest {

    private static boolean nestedDone = false;

    @Test
    void test1() {
        Assertions.assertFalse(nestedDone, 
            "Nested classes should execute after the enclosing tests");
    }

    @Nested
    class SomeNestedTest {
        @Test
        void test2() {
            nestedDone = true;
        }
    }

    @AfterAll
    static void recheck() {
        Assertions.assertTrue(nestedDone, "Nested class should be executed");
    }
}
Run Code Online (Sandbox Code Playgroud)

这确实在 IDE 中通过:
在此输入图像描述

但如果我尝试指定名称,则不在命令行中:

mvn test -Dtest=example.SomeTopLevelTest

[ERROR] Failures: 
[ERROR]   SomeTopLevelTest.recheck:27 Nested class should be executed ==> expected: <true> but was: <false>


mvn test -Dtest=example.SomeTopLevelTest*
[ERROR] Failures: 
[ERROR]   SomeTopLevelTest.test1:14 Nested classes should execute after the enclosing tests ==> expected: <false> but was: <true>
Run Code Online (Sandbox Code Playgroud)

Joc*_*ckX 5

类不执行的问题是一个已知问题, JUnit5Surefire@Nested问题跟踪器中均已报告该问题,但截至目前仍未解决。

目前的状况(使用 Maven 3.6.3、Junit5 5.7.2、Surefire 2.22.2 至 3.0.0-M5 进行测试):

A. 不选择测试

mvn test
Run Code Online (Sandbox Code Playgroud)

结果按预期执行所有测试类:首先来自封闭类的方法,然后是来自@Nested类的方法,逐级执行

B. 选择测试标准方式

mvn test -Dtest=example.SomeTopLevelTest
Run Code Online (Sandbox Code Playgroud)

excludes这显然会触发使用以下模式的默认万无一失:

<excludes>
    <exclude>**/*$*</exclude>
</excludes>
Run Code Online (Sandbox Code Playgroud)

为什么情况 A 不会发生这种情况是一个谜,但可以通过显式清除排除模式来覆盖此行为:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
            <excludes>
                <exclude/>
            </excludes>
        </configuration>
    </plugin>
Run Code Online (Sandbox Code Playgroud)

如果不修改 pom.xml 似乎不可能做到这一点。
并不能解决这个问题中发布的问题,因为嵌套类仍然首先执行。

C. 将通配符与 -Dtest 参数一起使用

mvn test -Dtest=example.SomeTopLevelTest*
Run Code Online (Sandbox Code Playgroud)

这显式选择了所有嵌套类,但是 - 正如问题中所述 - 导致首先执行嵌套类,所以这不是解决方案。

D. 使用包含

mvn test -DtestName=example.SomeTopLevelTest

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <includes>
            <include>${testName}</include>
        </includes>
    </configuration>
</plugin>
Run Code Online (Sandbox Code Playgroud)

显然include,模式的工作方式与参数完全不同-Dtest,因为这最终是通过问题测试的解决方案。通过此设置,testName可能是单个类、通配符模式或正则表达式

  • example.SomeTopLevelTest执行单个类中的所有测试方法
  • example/*- 包示例中的所有测试(包括嵌套),但不是子包
  • example/**- 包和子包中的所有测试
  • 也支持高级正则表达式