Junit 5 nested tests with several examples

0
2100

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 :

  1. Junit 5.5.2
  2. Maven 3
  3. Java 8
  4. 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 :

Junit 5 nested tests
=> 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

  1. Tests execution order in Junt Jupiter is not applicable for nested classes. But you can define order for nested test class methods.
  2. All the root test class test methods executes first either in defined order or in default order and then starts nested tests execution.
  3. 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 :

Junit 5 nested tests order
=> 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

  1. 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.
  2. @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()

LEAVE A REPLY

Please enter your comment!
Please enter your name here