JUnit Jupiter @Nested
annotation can be used to mark a nested class to be included in the test cases. When JUnit tests are executed, Nested classes are not scanned for test methods. We can explicitly mark them to be scanned for test cases using @Nested annotation.
JUnit 5 Nested Tests
JUnit Nested test classes should be non-static. Let’s look at a simple example of JUnit 5 Nested test class.
package com.journaldev.nested;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
public class NestedTestSimpleExample {
@Test
void test() {
System.out.println("Outer Class Test");
}
@Nested
class InnerClass {
@Test
void test() {
System.out.println("Inner Class Test");
}
}
}
Below image shows the JUnit execution report from Eclipse.
If we remove @Nested annotation from the inner class, then the tests inside that will not be executed.
JUnit Nested Tests Callback Methods
Nested test classes can have their own @BeforeEach
and @AfterEach
methods. However, if outer class @BeforeEach
and @AfterEach
methods will also get executed for nested class tests. Let’s extend our example to confirm this behavior.
package com.journaldev.nested;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
public class NestedTestSimpleExample {
@BeforeAll
static void setUpBeforeClass() throws Exception {
System.out.println("@BeforeAll - Outer Class");
}
@AfterAll
static void tearDownAfterClass() throws Exception {
System.out.println("@AfterAll - Outer Class");
}
@BeforeEach
void setUp() throws Exception {
System.out.println("@BeforeEach - Outer Class");
}
@AfterEach
void tearDown() throws Exception {
System.out.println("@AfterEach - Outer Class");
}
@Test
void test() {
System.out.println("Outer Class Test");
}
@Nested
class InnerClass {
@BeforeEach
void setUp() throws Exception {
System.out.println("@BeforeEach - Inner Class");
}
@AfterEach
void tearDown() throws Exception {
System.out.println("@AfterEach - Inner Class");
}
@Test
void test() {
System.out.println("Inner Class Test");
}
}
}
The console output of JUnit Test Execution clearly confirms this behavior.
@BeforeAll - Outer Class
@BeforeEach - Outer Class
Outer Class Test
@AfterEach - Outer Class
@BeforeEach - Outer Class
@BeforeEach - Inner Class
Inner Class Test
@AfterEach - Inner Class
@AfterEach - Outer Class
@AfterAll - Outer Class
If we want @BeforeAll and @AfterAll methods in the nested test class, then we have to explicitly set its lifecycle behavior to “per-class”. The default behavior of JUnit test cases is “per-method”.
package com.journaldev.nested;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
class NestedExampleTest {
@BeforeAll
static void setUpBeforeClass() throws Exception {
System.out.println("@BeforeAll - Outer Class");
}
@AfterAll
static void tearDownAfterClass() throws Exception {
System.out.println("@AfterAll - Outer Class");
}
@BeforeEach
void setUp() throws Exception {
System.out.println("@BeforeEach - Outer Class");
}
@AfterEach
void tearDown() throws Exception {
System.out.println("@AfterEach - Outer Class");
}
@Test
void outer_test() {
System.out.println("Outer Class test method");
}
@Nested
@TestInstance(Lifecycle.PER_CLASS)
class InnerClass {
@BeforeAll
void setUpBeforeClassInner() throws Exception {
System.out.println("@BeforeAll - Inner Class");
}
@AfterAll
void tearDownAfterClassInner() throws Exception {
System.out.println("@AfterAll - Inner Class");
}
@BeforeEach
void setUp() throws Exception {
System.out.println("@BeforeEach - Inner Class");
}
@AfterEach
void tearDown() throws Exception {
System.out.println("@AfterEach - Inner Class");
}
@Test
void inner_test() {
System.out.println("Inner Class test method");
}
}
}
Here is the console output of JUnit test:
@BeforeAll - Outer Class
@BeforeEach - Outer Class
Outer Class test method
@AfterEach - Outer Class
@BeforeAll - Inner Class
@BeforeEach - Outer Class
@BeforeEach - Inner Class
Inner Class test method
@AfterEach - Inner Class
@AfterEach - Outer Class
@AfterAll - Inner Class
@AfterAll - Outer Class
Summary
JUnit Nested Classes can be used to categorize our test cases into different modules. But the same thing can be achieved by having multiple test classes.