JUnit 5 test cases can be written inside a nested class as well. The nested class keeps the @Test
case code and @Test
result report much cleaner and organized. for this JUnit 5 provides us @Nested
annotation.
JUnit 5 nested class test case provides 2 main benefits.
- Now if required each test case can have its own pre and post test lifecycle.
- All test case methods coexist together, hence we cannot have duplicate method names in 1 class, but because the nested class provides an additional namespace and is independent of the parent, it can have methods as the same name of the parent, but yes methods within the nested class must have unique names.
Make sure to add @Nested
annotation on top of static class otherwise nested class test cases will not be considered.
package org.wesome.junit5;
public class AppleCalculator {
public int addApple(int apple1, int apple2) {
return apple1 + apple2;
}
public int subApple(int apple1, int apple2) {
return apple1 - apple2;
}
}
package org.wesome.junit5;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class AppleCalculatorTest {
@Test
void addAppleTest() {
System.out.println("AppleCalculatorTest.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("AppleCalculatorTest.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
@Nested
class AddAppleInnerClass {
@Test
void addAppleTestCase1() {
System.out.println("AddAppleInnerClass.addAppleTestCase1");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void addAppleTestCase2() {
System.out.println("AddAppleInnerClass.addAppleTestCase2");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
}
@Nested
class SubAppleInnerClass {
@Test
void subAppleTestCase1() {
System.out.println("SubAppleInnerClass.subAppleTestCase1");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
@Test
void subAppleTestCase2() {
System.out.println("SubAppleInnerClass.subAppleTestCase2");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
}
}
plugins {
id 'java'
}
group 'org.wesome'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
}
test {
useJUnitPlatform()
}
Generated report will be much cleaner, seggrigated and easy to read.
There is no limit to the nested class, we can create as many nested classes as required.
package org.wesome.junit5;
public class AppleCalculator {
public int addApple(int apple1, int apple2) {
return apple1 + apple2;
}
public int subApple(int apple1, int apple2) {
return apple1 - apple2;
}
}
package org.wesome.junit5;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class AppleCalculatorTest {
@Test
void addAppleTest() {
System.out.println("AppleCalculatorTest.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("AppleCalculatorTest.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
@Nested
class InnerClass1 {
@Test
void addAppleTest() {
System.out.println("InnerClass1.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("InnerClass1.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
}
@Nested
class InnerClass2 {
@Test
void addAppleTest() {
System.out.println("InnerClass2.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("InnerClass2.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
}
}
plugins {
id 'java'
}
group 'org.wesome'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
}
test {
useJUnitPlatform()
}
We can create a multi-level nested class structure, ie a nested class inside another nested class.
package org.wesome.junit5;
public class AppleCalculator {
public int addApple(int apple1, int apple2) {
return apple1 + apple2;
}
public int subApple(int apple1, int apple2) {
return apple1 - apple2;
}
}
package org.wesome.junit5;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class AppleCalculatorTest {
@Test
void addAppleTest() {
System.out.println("AppleCalculatorTest.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("AppleCalculatorTest.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
@Nested
class InnerClass1 {
@Test
void addAppleTest() {
System.out.println("InnerClass1.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("InnerClass1.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
@Nested
class InnerClass2 {
@Test
void addAppleTest() {
System.out.println("InnerClass2.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("InnerClass2.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
}
}
}
plugins {
id 'java'
}
group 'org.wesome'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
}
The life cycle method of the parent test case class will also be applicable for the tested class.
package org.wesome.junit5;
public class AppleCalculator {
public int addApple(int apple1, int apple2) {
return apple1 + apple2;
}
public int subApple(int apple1, int apple2) {
return apple1 - apple2;
}
}
package org.wesome.junit5;
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 static org.junit.jupiter.api.Assertions.assertEquals;
class AppleCalculatorTest {
@AfterAll
static void afterAll() {
System.out.println("AppleCalculatorTest.afterAll");
}
@BeforeAll
static void beforeAll() {
System.out.println("AppleCalculatorTest.beforeAll");
}
@Test
void addAppleTest() {
System.out.println("AppleCalculatorTest.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("AppleCalculatorTest.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
@BeforeEach
void setUp() {
System.out.println("AppleCalculatorTest.setUp");
}
@AfterEach
void tearDown() {
System.out.println("AppleCalculatorTest.tearDown");
}
@Nested
class InnerClass {
@Test
void addAppleTest() {
System.out.println("InnerClass.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("InnerClass.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
}
}
plugins {
id 'java'
}
group 'org.wesome'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
}
If not mentioned then Junit 5 life cycle is PER_METHOD
, a nested inner class can have all Junit 5 life cycle method except @BeforeAll
and @AfterAll
because the nested class cannot have static methods and both @BeforeAll
and @AfterAll
must be static.
package org.wesome.junit5;
public class AppleCalculator {
public int addApple(int apple1, int apple2) {
return apple1 + apple2;
}
public int subApple(int apple1, int apple2) {
return apple1 - apple2;
}
}
package org.wesome.junit5;
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 static org.junit.jupiter.api.Assertions.assertEquals;
class AppleCalculatorTest {
@Test
void addAppleTest() {
System.out.println("AppleCalculatorTest.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("AppleCalculatorTest.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
@Nested
class InnerClass {
@BeforeAll
void beforeAll() {
System.out.println("InnerClass.beforeAll");
}
@AfterAll
void afterAll() {
System.out.println("InnerClass.afterAll");
}
@BeforeEach
void setUp() {
System.out.println("InnerClass.setUp");
}
@AfterEach
void tearDown() {
System.out.println("InnerClass.tearDown");
}
@Test
void addAppleTest() {
System.out.println("InnerClass1.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("InnerClass1.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
}
}
plugins {
id 'java'
}
group 'org.wesome'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
}
If we need to add @BeforeAll
and @AfterAll
then we have to change default life cycle from PER_METHOD
to PER_CLASS
.
package org.wesome.junit5;;
public class AppleCalculator {
public int addApple(int apple1, int apple2) {
return apple1 + apple2;
}
public int subApple(int apple1, int apple2) {
return apple1 - apple2;
}
}
package org.wesome.junit5;
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 static org.junit.jupiter.api.Assertions.assertEquals;
class AppleCalculatorTest {
@Test
void addAppleTest() {
System.out.println("AppleCalculatorTest.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("AppleCalculatorTest.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class InnerClass {
@BeforeAll
void beforeAll() {
System.out.println("InnerClass.beforeAll");
}
@AfterAll
void afterAll() {
System.out.println("InnerClass.afterAll");
}
@BeforeEach
void setUp() {
System.out.println("InnerClass.setUp");
}
@AfterEach
void tearDown() {
System.out.println("InnerClass.tearDown");
}
@Test
void addAppleTest() {
System.out.println("InnerClass1.addAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(2, appleCalculator.addApple(1, 1), "1 apple + 1 apple is 2 apple");
}
@Test
void subAppleTest() {
System.out.println("InnerClass1.subAppleTest");
AppleCalculator appleCalculator = new AppleCalculator();
assertEquals(1, appleCalculator.subApple(2, 1), "2 apple - 1 apple is 1 apple");
}
}
}
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
}