How to create nested tests in JUnit

A well-written test suite will have multiple tests for a specific feature. By grouping related features, you can express the relationship between multiple groups of tests. One of the main benefits of grouping unit test classes is that you can reduce the amount of test code you write, since grouped tests share resources.


JUnit 5 allows you to create nested tests using the @Nested annotation. In this article, you will learn what the @Nested annotation is and how to use it.


What is a nested test?

JUnit’s @Nested annotation indicates that the class it is associated with is an inner class, which is a member of another class. A nested test is a test class that contains the @Nested annotation, since this means that there is one (or more) inner class inside a top-level test class. A nested class can appear inside a top-level class or inside a class that is also nested.

Creating Java classes for testing

A nested test class inherits all the features of its parent class. Therefore, the best time to create a nested test is when there is a logical grouping of test cases or when a single test case has different characteristics. A good example of this is when you want to test a class’s ability to create useful objects. Another example is when a single method has two or more purposes.

Here’s an example class you could use in a retail application, demonstrating how you can create a nested test.

public class Customer {
protected int customerId;
protected String customerName;
protected String customerCode;


public Customer() {
this.customerId = 0;
this.customerName = "";
this.customerCode ="";
}


public Customer(int customerId, String customerName, String customerCode) {
this.customerId = customerId;
this.customerName = customerName;
this.customerCode = customerCode;
}


public Customer(Customer customer) {
this.customerId = customer.customerId;
this.customerName = customer.customerName;
this.customerCode = customer.customerCode;
}


public int getCustomerId() {
return customerId;
}

public void setCustomerId(int customerId) {
this.customerId = customerId;
}

public String getCustomerName() {
return customerName;
}

public void setCustomerName(String customerName) {
this.customerName = customerName;
}

public String getCustomerCode() {
return customerCode;
}

public void setCustomerCode(String customerCode) {
this.customerCode = customerCode;
}


public double customerType(String customerCode) {
double discount = 0;

if (customerCode.toLowerCase().equals("pre")) {
discount = 0.10;
} else if (customerCode.toLowerCase().equals("gen")) {
discount = 0.02;
} else if (customerCode.toLowerCase().equals("new")) {
discount = 0.05;
}

return discount;
}


public double grandTotal(double total) {
double discount = customerType(customerCode);
double discountPercentage = total * discount;
double finalTotal = total - discountPercentage;
return finalTotal;
}
}

This Client class contains all the components of a Java Class, complete with two methods.

Creating a nested test with JUnit 5

The Customer class has several constructors, getters and setters, and two methods. You can create a nested class (inside the Customer test class) that creates a new Customer object and tests all of its components.

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

@DisplayName("Customer Test Class Showing How to Create Nested Tests.")
class CustomerTest {
protected int customerId = 301;
protected String customerName = "Mike Wilson";
protected String customerCode = "Pre";
protected double total = 600;

@Nested
@DisplayName("Customer Builder Nested Test Class Within a Top-Level Test Class")
class CustomerBuilderTest {
Customer customer = new Customer(customerId, customerName, customerCode);
double grandTotal = customer.grandTotal(total);

@Test
@DisplayName("Testing the Customer's Class Constructors, Getters and Setters, and Methods.")
void customerBuilder() {
assertAll(() -> {
assertEquals(customerId, customer.getCustomerId());
assertEquals(customerName, customer.getCustomerName());
assertEquals(customerCode, customer.getCustomerCode());
assertEquals(0.10, customer.customerType(customerCode));
assertEquals(540, grandTotal);
});
}
}
}

The CustomerTest class is the top-level test class for a nested CustomerBuilderTest class. CustomerBuilderTest creates a new Customer object and tests its components using assertion tests.

Running the CustomerTest test class produces the following successful test results:

Test class and test method names are descriptive and complete, thanks to the @DisplayName annotation.

Knowing how to test software is crucial

Technology is an important aspect of everyday life for most people. The stakes in building software that does exactly what it’s supposed to do has never been higher.

An autonomous car that misjudges its proximity to another object can cause a serious accident. Therefore, you must test your application at every stage of its development.

Leave a Comment