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
- When JUnit executes the tests it instantiate your
Child
, which first needs to call a Base
.
"A"
- Java classloader has not loaded Base
class yet, so it loads the class and - calls the static block.
"B"
- JUnit's runner sees @BeforeAll
annotation and checks wheter it has been called already and if not it calls the method.
"C"
- Now Java can finish instatiation of Child
so classloader can load it and calls the static block.
"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