1. Introduction
ReflectionTestUtils is a part of the Spring Test Context framework. It’s a collection for reflection-based utility methods used in a unit, and integration testing scenarios to set the non-public fields, invoke non-public methods, and inject dependencies.
In this tutorial, we’ll learn how to use ReflectionTestUtils in unit testing by going through several examples.
2. Maven Dependencies
We’ll start by adding the latest versions of all the necessary dependencies to our pom.xml:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.2.RELEASE</version>
<scope>test</scope>
</dependency>
The latest spring-context and spring-test dependencies can be downloaded from the Maven Central repository.
3. Using ReflectionTestUtils to Set a Value of a Non-Public Field
Suppose we need to use an instance of a class having a private field, without a public setter method in our unit test.
We’ll start by creating it:
public class Employee {
private Integer id;
private String name;
// standard getters/setters
}
Normally we can’t access the private field id to assign a value for testing because there isn’t a public setter method for it.
So we’ll use the ReflectionTestUtils.setField method to assign a value to the private member id:
@Test
public void whenNonPublicField_thenReflectionTestUtilsSetField() {
Employee employee = new Employee();
ReflectionTestUtils.setField(employee, "id", 1);
assertTrue(employee.getId().equals(1));
}
4. Using ReflectionTestUtils to Invoke a Non-Public Method
Now let’s imagine that we have a private method, employeeToString, in the Employee class:
private String employeeToString(){
return "id: " + getId() + "; name: " + getName();
}
We can write a unit test for the employeeToString method as below, even though it doesn’t have any access from outside of an Employee class:
@Test
public void whenNonPublicMethod_thenReflectionTestUtilsInvokeMethod() {
Employee employee = new Employee();
ReflectionTestUtils.setField(employee, "id", 1);
employee.setName("Smith, John");
assertTrue(ReflectionTestUtils.invokeMethod(employee, "employeeToString")
.equals("id: 1; name: Smith, John"));
}
5. Using ReflectionTestUtils to Inject Dependencies
Let’s say we want to write a unit test for the following Spring component having a private field with the @Autowired annotation:
@Component
public class EmployeeService {
@Autowired
private HRService hrService;
public String findEmployeeStatus(Integer employeeId) {
return "Employee " + employeeId + " status: " + hrService.getEmployeeStatus(employeeId);
}
}
Now we can implement the HRService component as below:
@Component
public class HRService {
public String getEmployeeStatus(Integer employeeId) {
return "Inactive";
}
}
Furthermore, we’ll create a mock implementation for the HRService class by using Mockito. We’ll inject this mock into the EmployeeService instance, and we’ll use it in our unit test:
HRService hrService = mock(HRService.class);
when(hrService.getEmployeeStatus(employee.getId())).thenReturn("Active");
Because hrService is a private field without a public setter, we’ll use the ReflectionTestUtils.setField method to inject the mock we created above into this private field:
EmployeeService employeeService = new EmployeeService();
ReflectionTestUtils.setField(employeeService, "hrService", hrService);
Finally, our unit test will look similar to this:
@Test
public void whenInjectingMockOfDependency_thenReflectionTestUtilsSetField() {
Employee employee = new Employee();
ReflectionTestUtils.setField(employee, "id", 1);
employee.setName("Smith, John");
HRService hrService = mock(HRService.class);
when(hrService.getEmployeeStatus(employee.getId())).thenReturn("Active");
EmployeeService employeeService = new EmployeeService();
// Inject mock into the private field
ReflectionTestUtils.setField(employeeService, "hrService", hrService);
assertEquals(
"Employee " + employee.getId() + " status: Active",
employeeService.findEmployeeStatus(employee.getId()));
}
We should note that this technique is a workaround for the fact that we’re using field injection in our bean class. If we switched to constructor injection, then this approach wouldn’t be necessary.
6. Conclusion
In this article, we demonstrated how to use ReflectionTestUtils in unit testing by going through several examples.
Code samples, as always, can be found over on Github.