Nested Map Assertions in Java with JUnit
In Java applications, nested data structures are commonplace, especially when dealing with configurations, JSON responses, or complex data representations. One such structure is the nested map. This article focuses on the theory behind nested maps, their structures, and the techniques used for asserting their contents effectively in unit tests using JUnit.
Prerequisites:
- Basic understanding of Java and the JUnit Framework.
- Maven for dependency management.
- JDK and IntelliJ IDEA installed on your system.
Maven Dependency
Add the following Maven dependency to the pom.xml file:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
Understanding Nested Maps
What is a Map?
In Java, a Map is an interface that associates unique keys with specific values, forming part of the Java Collections Framework, and is utilized for storing data in key-value pairs.. Here are some characteristics of maps:
- Dynamic Size: Maps can dynamically grow as new key-value pairs are added.
- Common Implementations: The most commonly used implementations of the Map interface include:
- HashMap: Provides constant uptime for basic operations and does not maintain any order.
- LinkedHashMap: checks which entries in the map are linked, and stores the order of insertion.
- TreeMap: Uses a sorted map, sorting keys in their natural order or based on a given comparator.
What is a Nested Map?
A nested map is a map where the values themselves are maps. This format allows for a more systematic organization of the data. For example, consider a nested map representing a library system in which each type of book (e.g., fiction, nonfiction) is a collection of books along with their description (e.g. title, author, quantity).
Example of a Nested Map Structure:
Map<String, Map<String, Integer>> library = new HashMap<>();
library.put("Fiction", Map.of("1984", 3, "Brave New World", 5));
library.put("Non-Fiction", Map.of("Sapiens", 2, "Educated", 4));
Real-World Use Case of Employee Management System
In this example, we will create a nested map structure that represents an employee management system. Each department will have multiple employees, and each employee will have a record of projects.
The data structure will look like this:
- Outer Map: Key = Department, Value = Inner Map
- Inner Map: Key = Employee Name, Value = Employee Object
- Employee Object: Contains employee details such as ID, salary, and a
List<String>
representing their projects.
Step 1: Create a New Maven Project
Create a new Maven project using IntelliJ IDEA with the following options:
- Name: nested-map-assertion
- Build system: Maven
Click on the Create button.

Project Structure
Once project creation done, set the folder structure as shown in the below image:

Step 2: Add the JUnit 5 dependencies to pom.xml
Open the pom.xml file and add the following JUnit 5 dependencies into the Maven project.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gfg</groupId>
<artifactId>nested-map-assertion</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
</build>
</project>
Step 3: Define the Employee Model
Define the Employee model class and add the following code into it.
package com.gfg;
import java.util.List;
public class Employee {
private int id;
private double salary;
private List<String> projects;
public Employee(int id, double salary, List<String> projects) {
this.id = id;
this.salary = salary;
this.projects = projects;
}
public int getId() {
return id;
}
public double getSalary() {
return salary;
}
public List<String> getProjects() {
return projects;
}
// Equals and hashCode methods for assertion comparison
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
if (id != employee.id) return false;
if (Double.compare(employee.salary, salary) != 0) return false;
return projects != null ? projects.equals(employee.projects) : employee.projects == null;
}
@Override
public int hashCode() {
int result;
long temp;
result = id;
temp = Double.doubleToLongBits(salary);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (projects != null ? projects.hashCode() : 0);
return result;
}
}
Step 4: Create the EmployeeDataProvider Class
Create the EmployeeDataProvider.java
file, which will return the nested map:
package com.gfg;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EmployeeDataProvider {
public static Map<String, Map<String, Employee>> getEmployeeData() {
Map<String, Map<String, Employee>> departmentEmployees = new HashMap<>();
// Define employees for the Engineering department
Map<String, Employee> engineeringEmployees = new HashMap<>();
engineeringEmployees.put("John Doe", new Employee(101, 75000, List.of("Project A", "Project B")));
engineeringEmployees.put("Jane Smith", new Employee(102, 80000, List.of("Project C")));
// Define employees for the HR department
Map<String, Employee> hrEmployees = new HashMap<>();
hrEmployees.put("Alice Johnson", new Employee(201, 50000, List.of("Project D")));
hrEmployees.put("Bob Brown", new Employee(202, 55000, List.of("Project E", "Project F")));
// Add to outer map
departmentEmployees.put("Engineering", engineeringEmployees);
departmentEmployees.put("HR", hrEmployees);
return departmentEmployees;
}
}
Step 5: MainApplication Class
In the main class, add logic to print the employee details as output:
package com.gfg;
import java.util.Map;
public class MainApplication {
public static void main(String[] args) {
// Get the nested map structure from EmployeeDataProvider
Map<String, Map<String, Employee>> departmentEmployees = EmployeeDataProvider.getEmployeeData();
// Iterate over each department
departmentEmployees.forEach((department, employees) -> {
System.out.println("Department: " + department);
// Iterate over each employee in the department
employees.forEach((employeeName, employee) -> {
System.out.println(" Employee: " + employeeName);
System.out.println(" ID: " + employee.getId());
System.out.println(" Salary: " + employee.getSalary());
System.out.println(" Projects: " + employee.getProjects());
});
});
}
}
Step 5: Create the Test Class
Create the EmployeeTest.java file and this class contains the unit tests to assert the nested map.
package com.gfg;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class EmployeeTest {
@Test
public void testEmployeeData() {
// Get the expected nested map structure
Map<String, Map<String, Employee>> expectedData = Map.of(
"Engineering", Map.of(
"John Doe", new Employee(101, 75000, List.of("Project A", "Project B")),
"Jane Smith", new Employee(102, 80000, List.of("Project C"))
),
"HR", Map.of(
"Alice Johnson", new Employee(201, 50000, List.of("Project D")),
"Bob Brown", new Employee(202, 55000, List.of("Project E", "Project F"))
)
);
// Get the actual nested map structure from the data provider
Map<String, Map<String, Employee>> actualData = EmployeeDataProvider.getEmployeeData();
// Assert the expected data matches the actual data
assertEquals(expectedData, actualData);
}
}
Explanation:
- Test Setup: The testEmployeeDataStructure() method retrieves the nested map structure from the EmployeeDataProvider.
- Asserting the Outer Map: The outer map represents the departments, and we first assert that there are exactly the two departments.
- Asserting the Inner Map: For the each department, we assert that the correct number of the employees is present.
- Asserting Employee Details: We go one level deeper to the assert each employee’s id, salary, and the list of the projects they are working on it.
Step 6: Run the Application
Once the project is completed, we will run and it will display the below output:

Step 7: Running the Test
We can execute the test suite using following maven command.
mvn test
Output:
All assertions should pass if the method behaves as the expected.

This example project demonstrated how to assert the nested maps in the JUnit effectively. This example focused on the employee management system with multiple levels of the nesting, including the lists inside the maps. Such structures are common in the real world applications, and this method can ensure and thoroughly validate the data structure using clear and concise assertions.