JUnit 5 Nested Tests

Filed Under: JUnit

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.

JUnit Nested Test Class

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.

You can check out the complete code from our JUnit 5 example project GitHub Repository.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages