JUnit BeforeAll 与静态块 - 执行顺序

Gav*_*los 6 java junit

我有一个简单的问题。我有这样的类结构:基类和子类(关系是继承)。@BeforeAll 来自 JUnit5。

 abstract class Base {
    static{
        System.out.println("A");
    }

    @BeforeAll
    public static void setUp() {
        System.out.println("B");
    }
}


class Child extends Base {
    static {
        System.out.println("C");
    }

    @Test
    public void test() {
        System.out.println("D");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,在我看来,执行顺序应该是:ACBD,但是,这看起来像:ABCD 我正在搜索信息,但我找不到任何有关它的信息。

hra*_*cek 8

该顺序由 Java 类加载和 JUnit5 的 [1] 确定TestEngine(如果我是正确的)。所以JUnit的测试执行和Java的类加载是有区别的。

@BeforeAll 与静态块

记住这两者之间的区别。

静态块- 仅当 Java 的类加载器将类加载到内存中时执行一次,例如创建第一个类实例。

@BeforeAll- JUnit 的测试引擎在当前测试类中的所有测试之前执行方法。

因此,如果您有另一个测试类扩展Base并运行所有测试,则静态块将仅执行一次,而@BeforeAll两次(每个测试类)。

订单说明

  1. 当 JUnit 执行测试时,它会实例化您的Child,它首先需要调用Base.
  2. "A"- Java 类加载器尚未加载Base类,因此它加载类并 - 调用静态块
  3. "B"- JUnit 的运行程序查看@BeforeAll注释并检查它是否已被调用,如果没有,则调用该方法。
  4. "C"- 现在Java可以完成实例化,Child因此类加载器可以加载它并调用静态块。
  5. "D"-Child被初始化并@Test执行注释的方法。

现在想象一下还有另一个class例如AnotherChild扩展Base。我们正在执行两个测试类ChildAnotherChild,因此 JUnit 必须调用@BeforeAll 两次,但 JavaBase在第一个测试类执行期间已经加载了类,因此它只会被调用一次

请注意,这是粗略简化的情况,实际上有点复杂(像往常一样)。


[1] https://junit.org/junit5/docs/current/api/org.junit.platform.engine/org/junit/platform/engine/TestEngine.html