import org.junit.jupiter.api.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class OuterTest { @BeforeAll void beforeAllOuter() { System.out.println("Outer beforeAll"); } @BeforeEach void beforeEachOuter() { System.out.println("Outer beforeEach"); } @Test void outerTest() { System.out.println("Outer test"); } @Nested @TestInstance(TestInstance.Lifecycle.PER_CLASS) class InnerTest { @BeforeAll void beforeAllInner() { System.out.println("Inner beforeAll"); } @BeforeEach void beforeEachInner() { System.out.println("Inner beforeEach"); } @Test void innerTest() { System.out.println("Inner test"); } } }
JUnit 5 runs @BeforeAll methods in the outer class first, then in the nested class before any tests in that nested class. @BeforeEach methods run before each test, starting from outer to inner. So the order is:
- Outer beforeAll
- Inner beforeAll
- Outer beforeEach
- Outer test
- Outer beforeEach
- Inner beforeEach
- Inner test
import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class OuterTest { int testCount = 0; @Test void outerTest() { testCount++; } @Nested class InnerTest { @Test void innerTest() { testCount++; } } @AfterAll void afterAll() { // Assertion here } }
The variable testCount increments once per test method run. Since there is one test in the outer class and one in the nested class, the total should be exactly 2. The assertion assertEquals(2, testCount); checks this precisely.
import org.junit.jupiter.api.*; public class OuterTest { @Nested class InnerTest { @BeforeAll void setup() { System.out.println("Setup Inner"); } @Test void test() { System.out.println("Inner test"); } } }
In JUnit 5, @BeforeAll methods in nested classes must be static unless the nested class is annotated with @TestInstance(Lifecycle.PER_CLASS). Otherwise, the method will not run and the test lifecycle is broken.
By default, JUnit 5 creates a new instance of the test class for each test method (PER_METHOD lifecycle). This applies to nested classes as well unless overridden by @TestInstance(Lifecycle.PER_CLASS).
Annotating the nested class with @TestInstance(TestInstance.Lifecycle.PER_CLASS) tells JUnit to create one instance of the nested class for all its tests, allowing instance fields to hold shared state. Static fields or methods are not required.