
Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:
Once the early-adopter seats are all used, the price will go up and stay at $33/year.
Last updated: May 11, 2024
In this tutorial, we’ll learn how to mock private fields with Mockito. Mockito is a popular mocking framework often used with JUnit for creating mock objects in Java. It doesn’t inherently support mocking private fields; however, we can use different approaches to mock private fields with Mockito.
Let’s examine a few of them.
We’ll start by creating the classes that we’ll use in our examples. We’ll create a class with a private field and a test class to test it.
First, we’ll create a simple class with a private field:
public class MockService {
private final Person person = new Person("John Doe");
public String getName() {
return person.getName();
}
}
The MockService class has a private field person of type Person. It also has a method, getName(), that returns the name of the person. As we can see, no setter method exists for the person field. So we can’t set the field directly, or change the value of the field.
Now we’ll create the Person class:
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
The Person class has a private field name and a getter method for the field.
Next, we’ll create a test class to test the MockService class:
public class MockServiceUnitTest {
private Person mockedPerson;
@BeforeEach
public void setUp(){
mockedPerson = mock(Person.class);
}
}
We create an instance of the Person class and mock it using Mockito. In the next sections, we’ll look at ways to use this mocked instance to replace the private field of the MockService class.
One of the ways to set the private field is to use the Java Reflection API. This is a good method because it doesn’t require any additional dependencies. We can first make the field accessible, and then set the value of the field to the mocked instance.
Let’s look at the code to do this:
@Test
void givenNameChangedWithReflection_whenGetName_thenReturnName() throws Exception {
Class<?> mockServiceClass = Class.forName("com.baeldung.mockprivate.MockService");
MockService mockService = (MockService) mockServiceClass.getDeclaredConstructor().newInstance();
Field field = mockServiceClass.getDeclaredField("person");
field.setAccessible(true);
field.set(mockService, mockedPerson);
when(mockedPerson.getName()).thenReturn("Jane Doe");
Assertions.assertEquals("Jane Doe", mockService.getName());
}
We use the Class.forName() method to get the class object of the MockService class. Then we create an instance of the MockService class using the getDeclaredConstructor() method.
Next, we use the getDeclaredField() method to get the person field of the MockService class. We make the field accessible using the setAccessible() method, and set the value of the field to the mocked instance using the set() method.
Finally, we can mock the getName() method of the Person class, and test the getName() method of the MockService class to return the mocked value.
Similar to Java Reflection API, JUnit 5 also provides utility methods to set private fields. We can use the ReflectionUtils class of JUnit 5 to set a value to the private field:
@Test
void givenNameChangedWithReflectionUtils_whenGetName_thenReturnName() throws Exception {
MockService mockService = new MockService();
Field field = ReflectionUtils
.findFields(MockService.class, f -> f.getName().equals("person"),
ReflectionUtils.HierarchyTraversalMode.TOP_DOWN)
.get(0);
field.setAccessible(true);
field.set(mockService, mockedPerson);
when(mockedPerson.getName()).thenReturn("Jane Doe");
Assertions.assertEquals("Jane Doe", mockService.getName());
}
This method works in the same way as the previous method. The main difference is how we get the field:
This gives us the field, and we can set the field’s value once again and perform the test.
If we’re using Spring for our project, Spring Test provides a utility class, ReflectionTestUtils, to set private fields.
Let’s start by adding the Spring Test dependency to our project:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.25</version>
<scope>test</scope>
</dependency>
Alternatively, if using Spring Boot, we could use the Spring Boot Starter Test dependency to do the same.
Next, let’s use this class in our test to enable the mocking:
@Test
void givenNameChangedWithReflectionTestUtils_whenGetName_thenReturnName() throws Exception {
MockService mockService = new MockService();
ReflectionTestUtils.setField(mockService, "person", mockedPerson);
when(mockedPerson.getName()).thenReturn("Jane Doe");
Assertions.assertEquals("Jane Doe", mockService.getName());
}
Here, we use the ReflectionTestUtils.setField() method to set the private field. Internally, this too uses the Java Reflection API to set the field, but removes the need for boilerplate code.
In this article, we looked at different ways to mock private fields with Mockito. We explored the Java Reflection API, JUnit 5, and Spring Test to mock private fields.