6

I have simple question. I have structure of classes like this: base class and child class(relationship is inheritance). @BeforeAll is from 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");
    }
}

So, In my opinion, the order of execution should be: ACBD but, this look like : ABCD I was searching information, but I could not find anyting about it.

Nilanka Manoj
  • 3,527
  • 4
  • 17
  • 48
Gavlos
  • 197
  • 1
  • 14
  • Does this answer your question? [Java Constructors - Order of execution in an inheritance hierarchy](https://stackoverflow.com/questions/19407187/java-constructors-order-of-execution-in-an-inheritance-hierarchy) – JAR Mar 19 '20 at 07:07
  • No, this is a another case :/ – Gavlos Mar 19 '20 at 07:10
  • Note that it makes no difference whether `Base` is abstract or not. – David Tonhofer Jun 21 '23 at 15:52
  • Link to the `@BeforeAll` docs for reference (Junit5 5.4.0): [@BeforeAll](https://junit.org/junit5/docs/5.4.0/api/org/junit/jupiter/api/BeforeAll.html) – David Tonhofer Jun 21 '23 at 15:59

1 Answers1

8

The order is determined by Java classloading and JUnit5's TestEngine [1] (If I'm correct). So there's a difference between JUnit's test execution and Java's class loading.

@BeforeAll vs static block

Remember difference between these two.

static blocks - are executed only once when Java's classloader loads the class in memory e.g. creating a first class instance.

@BeforeAll - methods are executed by JUnit's test engine before all tests in the current test class.

So if you would have another test class extending Base and run all tests, static block will be executed only once, whereas @BeforeAll twice (per each test class).

Explanation of order

  1. When JUnit executes the tests it instantiate your Child, which first needs to call a Base.
  2. "A" - Java classloader has not loaded Base class yet, so it loads the class and - calls the static block.
  3. "B" - JUnit's runner sees @BeforeAll annotation and checks wheter it has been called already and if not it calls the method.
  4. "C" - Now Java can finish instatiation of Child so classloader can load it and calls the static block.
  5. "D" - Child is initialized and method annotated by @Test is executed.

Now imagine there's another class e.g. AnotherChild extending Base. We are executing two test classes Child and AnotherChild, so JUnit has to call @BeforeAll twice, but Java already loaded Base class during execution of the first test class, so it will be called only once.

Note, that this is roughly simplified situation and in reality it's a bit complicated (as usual).


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

hradecek
  • 2,455
  • 2
  • 21
  • 30
  • The mystery is in point (3). How does JUnit insert itself into the JVM classloading process so that `Base.setUp()` is run before the class statics of `Child` are run? More interestingly, what kind of requirement might that solve? Note that if one overrides `setUp()` in `Child` without the `@BeforeAll` annotation, none of the `setUp()` is run. If one overrides `setUp()` in `Child` with the `@BeforeAll` annotation, only the `setUp()` of `Child` is run. – David Tonhofer Jun 21 '23 at 15:50