Nested class lifecycle helps organize tests in groups and control how often setup and cleanup happen for each group.
Nested class lifecycle in JUnit
import org.junit.jupiter.api.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) class OuterTest { @BeforeAll void beforeAllOuter() { // runs once before all tests in OuterTest } @Nested @TestInstance(TestInstance.Lifecycle.PER_CLASS) class InnerTest { @BeforeAll void beforeAllInner() { // runs once before all tests in InnerTest } @Test void testSomething() { // test code } } }
Use @Nested to create a nested test class inside an outer test class.
Lifecycle annotations like @BeforeAll run once per class instance.
import org.junit.jupiter.api.*; class OuterTest { @BeforeAll static void setupAll() { System.out.println("Setup once for all tests"); } @Nested class GroupOne { @BeforeEach void setupEach() { System.out.println("Setup before each test in GroupOne"); } @Test void testA() { System.out.println("Running testA"); } } }
@TestInstance(PER_CLASS) allows @BeforeAll to be non-static in nested classes.import org.junit.jupiter.api.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) class OuterTest { @Nested @TestInstance(TestInstance.Lifecycle.PER_CLASS) class InnerTest { @BeforeAll void init() { System.out.println("Init once for InnerTest"); } @Test void testOne() { System.out.println("Test one running"); } } }
This test class has two nested groups: AdditionTests and SubtractionTests. Setup methods run at different times for each group. Assertions check correct math results.
import org.junit.jupiter.api.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) class CalculatorTest { @BeforeAll void setupAll() { System.out.println("Setup for all tests"); } @Nested @TestInstance(TestInstance.Lifecycle.PER_CLASS) class AdditionTests { @BeforeAll void setupAddition() { System.out.println("Setup for addition tests"); } @Test void testAddPositive() { int result = 2 + 3; Assertions.assertEquals(5, result); System.out.println("testAddPositive passed"); } @Test void testAddNegative() { int result = -1 + -1; Assertions.assertEquals(-2, result); System.out.println("testAddNegative passed"); } } @Nested class SubtractionTests { @BeforeEach void setupSubtraction() { System.out.println("Setup before each subtraction test"); } @Test void testSubtract() { int result = 5 - 3; Assertions.assertEquals(2, result); System.out.println("testSubtract passed"); } } }
Nested classes help keep tests organized and readable.
Use @TestInstance(TestInstance.Lifecycle.PER_CLASS) to allow non-static @BeforeAll in nested classes.
Setup in outer class runs before nested class setups.
Nested classes group related tests inside a main test class.
Lifecycle annotations control setup and cleanup timing per class or test.
Using nested lifecycle improves test organization and efficiency.
Practice
@Nested class inside a test class?Solution
Step 1: Understand the role of @Nested
The@Nestedannotation allows grouping related test methods inside inner classes to organize tests logically.Step 2: Compare other options
The other options describe unrelated features: disabling tests temporarily, running tests in parallel automatically, and creating separate test suite files, which are not the purpose of@Nested.Final Answer:
To group related tests together for better organization -> Option AQuick Check:
@Nested groups tests = C [OK]
- Thinking @Nested runs tests in parallel
- Confusing @Nested with @Disabled
- Assuming @Nested creates separate test files
@Nested class?Solution
Step 1: Identify lifecycle annotations for nested classes
In JUnit 5,@BeforeAllruns once before all tests in the class, including nested classes if used inside them.Step 2: Differentiate from other annotations
@BeforeEachruns before each test method, not once;@AfterEachand@AfterAllrun after tests, so they don't fit the requirement.Final Answer:
@BeforeAll -> Option AQuick Check:
Run once before all tests = @BeforeAll [OK]
- Using @BeforeEach instead of @BeforeAll for once-only setup
- Confusing @AfterAll with setup annotations
- Not placing @BeforeAll inside nested class
class OuterTest {
@BeforeAll
static void setupOuter() { System.out.println("Outer setup"); }
@Nested
class InnerTest {
@BeforeAll
static void setupInner() { System.out.println("Inner setup"); }
@Test
void testOne() { System.out.println("Test one"); }
}
}
What will be the order of printed lines when running testOne()?Solution
Step 1: Understand lifecycle order in nested classes
The@BeforeAllin the outer class runs first, then the@BeforeAllin the nested class, followed by the test method.Step 2: Trace the print statements
First prints "Outer setup", then "Inner setup", then "Test one" as per the method calls.Final Answer:
Outer setup\nInner setup\nTest one -> Option BQuick Check:
Outer before all, then inner before all, then test [OK]
- Assuming nested @BeforeAll runs before outer
- Mixing order of test and setup prints
- Forgetting static requirement for @BeforeAll in nested
@BeforeAll from running?
class OuterTest {
@Nested
class InnerTest {
@BeforeAll
void setup() { System.out.println("Setup"); }
@Test
void test() { System.out.println("Test"); }
}
}Solution
Step 1: Check @BeforeAll method requirements in nested classes
In JUnit 5,@BeforeAllmethods inside nested classes must be static unless the nested class is annotated with@TestInstance(Lifecycle.PER_CLASS).Step 2: Analyze the given code
The@BeforeAllmethod is non-static and the nested class is not annotated with@TestInstance, so this causes a runtime error.Final Answer:
@BeforeAll method must be static in nested classes -> Option CQuick Check:
@BeforeAll in nested must be static unless @TestInstance used [OK]
- Thinking @BeforeAll cannot be used in nested classes
- Forgetting static keyword on @BeforeAll method
- Confusing @BeforeAll with @BeforeEach
Solution
Step 1: Understand static requirement for @BeforeAll in nested classes
By default,@BeforeAllmethods in nested classes must be static because nested classes are instance classes.Step 2: Use @TestInstance(Lifecycle.PER_CLASS) to allow non-static @BeforeAll
Annotating the nested class with@TestInstance(Lifecycle.PER_CLASS)changes lifecycle so@BeforeAllcan be non-static, allowing setup without static nested class.Step 3: Evaluate other options
Make the nested class static and keep@BeforeAllmethod static requires static nested class, which is not desired. Use@BeforeEachinstead of@BeforeAllin nested class changes setup frequency. Move all tests to the outer class and remove nested classes removes nested structure, losing organization.Final Answer:
Annotate the nested class with @TestInstance(Lifecycle.PER_CLASS) and make the @BeforeAll method non-static -> Option DQuick Check:
@TestInstance(PER_CLASS) allows non-static @BeforeAll in nested [OK]
- Making nested class static when not needed
- Using @BeforeEach instead of @BeforeAll for once-only setup
- Removing nested classes to fix lifecycle issues
Ready to prove it?
Pass the test and this pattern moves unknown
