Spring Top

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE COURSE

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.

Spring bottom

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE LESSONS

Leave a Reply

avatar
  Subscribe  
Notify of