How to Create Nested Tests in JUnit

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


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


What is a nested test?

JUnit’s @Nested annotation signals that the class it is associated with is an inner class that is a member of another class. A nested test is a test class that contains the @Nested annotation, as this means that there is one (or more) inner class inside a top-level test class. A nested class can appear within a top-level class or within 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 distinct 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 that you can use in a retail application that shows 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 Customer 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 (within 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 test class of 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:

The names of the test classes and the test method are meaningful and understandable 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.

A self-driving car that misjudges its proximity to another object can cause a serious accident. Therefore, you need to test your application at every stage of its development.

Leave a Reply

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