Guide to ReflectionTestUtils for Unit Testing

1. Introduction

ReflectionTestUtils is
a part of Spring Test Context framework. It is 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 take a look at how we can use
the ReflectionTestUtils in unit testing by going through several
examples.

2. Maven Dependencies

Let’s start by adding the latest versions of all necessary dependencies
needed for our examples 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,
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.

Let’s start by creating it:

public class Employee {
    private Integer id;
    private String name;

    // standard getters/setters
}

Normally we cannot access the private field id to assign a value for
testing, because there isn’t a public setter method for it.

We can then use 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

Let’s now imagine that we have a private method employeeToString in
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 that 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);
    }
}

We can now implement the HRService component as below:

@Component
public class HRService {

    public String getEmployeeStatus(Integer employeeId) {
        return "Inactive";
    }
}

Furthermore, let’s 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 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()));
}

6. Conclusion

In this tutorial, we showed how to use ReflectionTestUtils in unit
testing by going through several examples.

Code samples, as always, can be found
over
on Github
.

Leave a Reply

Your email address will not be published.