Junit 5 nested tests is used to express the relationship among several groups of tests and to represent tests in hierarchy. @Nested
annotation allows you to have an inner class in a test class and that is another test class. Writing proper nested classes improves maintainability and readability of tests and test results.
@Nested annotation is used to signal that the annotated class is a nested test and a nested test class must be non-static inner class.
Technologies used in following examples :
- Junit 5.5.2
- Maven 3
- Java 8
- Spring Tool Suite 3.9.8
1. Junit 5 nested tests
1.1. A simple nested test example
@DisplayName("Root Test") public class Junit5_NestedTests_Test { @Test void test1() { System.out.println("=> test1()"); } @Nested @DisplayName("Nested Test A") class TestA { @Test void testA_test1() { System.out.println("=> testA_test1()"); } @Nested @DisplayName("Nested Test AA") class TestAA { @Test void testAA_test1() { System.out.println("=> testAA_test1()"); } } } @Nested @DisplayName("Nested Test B") class TestB { @Test void testB_test1() { System.out.println("=> testB_test1()"); } } }
Output :
=> test1() => testA_test1() => testAA_test1() => testB_test1()
1.2. can not declare @BeforeAll
and @AfterAll
methods in nested tests by default. The reason is that Java does not allow static
members in inner classes. You allow to include @BeforeAll
and @AfterAll
in nested class only if the test instance lifecycle mode is per_class @TestInstance(Lifecycle.PER_CLASS)
Note that if Root class declared as @TestInstance(Lifecycle.PER_CLASS)
, that behavior wont be inherited to nested classes.
public class Junit5_NestedTests_Test2 { @Test void test1() { System.out.println("=> test1()"); } @Nested @TestInstance(Lifecycle.PER_CLASS) class TestA { @BeforeAll void testA_BeforeAll() { System.out.println("=> testA_BeforeAll()"); } @BeforeEach void testA_BeforeEach() { System.out.println("=> testA_BeforeEach()"); } @Test void testA_test1() { System.out.println("=> testA_test1()"); } } }
Output :
=> test1() => testA_BeforeAll() => testA_BeforeEach() => testA_test1()
2. Test method execution order in nested tests
- Tests execution order in Junt Jupiter is not applicable for nested classes. But you can define order for nested test class methods.
- All the root test class test methods executes first either in defined order or in default order and then starts nested tests execution.
- If you have same level of multiple nested classes in root test class, they will be executed in alphanumerical order of their class names.
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class Junit5_Nested_Order_Test { @Test @Order(1) void test2() { System.out.println("=> test2()"); } @Nested @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class TestB { @Test @Order(1) void testB_test2() { System.out.println("=> testB_test2()"); } @Test @Order(2) void testB_test1() { System.out.println("=> testB_test1()"); } } @Nested @TestMethodOrder(MethodOrderer.Alphanumeric.class) class TestC { @Test void testC_test2() { System.out.println("=> testC_test2()"); } @Test void testC_test1() { System.out.println("=> testC_test1()"); } } @Nested class TestA { @Test void testA_test2() { System.out.println("=> testA_test2()"); } @Test void testA_test1() { System.out.println("=> testA_test1()"); } @Nested class TestAA { @Test void testAA_test2() { System.out.println("=> testAA_test2()"); } @Test void testAA_test1() { System.out.println("=> testAA_test1()"); } } @Nested class TestAB { @Test void testAB_test1() { System.out.println("=> testAB_test1()"); } @Nested class TestABA { @Test void testABA_test1() { System.out.println("=> testABA_test1()"); } } } @Test void testA_test3() { System.out.println("=> testA_test3()"); } } @Test @Order(2) void test3() { System.out.println("=> test3()"); } @Test @Order(3) void test1() { System.out.println("=> test1()"); } }
Output :
=> test2() => test3() => test1() => testA_test1() => testA_test2() => testA_test3() => testAA_test1() => testAA_test2() => testAB_test1() => testABA_test1() => testB_test2() => testB_test1() => testC_test1() => testC_test2()
3. Timeout in nested tests
- To apply the same timeout to all Junit Jupiter test methods within a test class and all of its
@Nested
classes, you can declare the@Timeout
annotation at the class level. @Timeout
annotations declared at the class level are not applied to lifecycle methods.
@Timeout(value = 900, unit = TimeUnit.MILLISECONDS) public class Junit5_Nested_Tiemout_Test { @Test void test1() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(1000); // waits 1000 ms System.out.println("=> ---test1()"); } @Test void test2() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(500); // waits 500 ms System.out.println("=> ---test2()"); } @Nested @TestInstance(Lifecycle.PER_CLASS) class TestA { @BeforeAll void testA_BeforeAll() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(1000); // waits 1000 ms System.out.println("=> ---testA_BeforeAll()"); } @BeforeEach void testA_BeforeEach() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(1000); // waits 1000 ms System.out.println("=> ---testA_BeforeEach()"); } @Test void testA_test1() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(1000); // waits 1000 ms System.out.println("=> ---testA_test1()"); } @Test void testA_test2() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(100); // waits 100 ms System.out.println("=> ---testA_test2()"); } } }
Output :
=> ---test2() => ---testA_BeforeAll() => ---testA_BeforeEach() => ---testA_BeforeEach() => ---testA_test2()