How to mock a private member with Mockito
We often get the scenarios while writing the unit tests for java applications where we need to mock the private members of a class. Since these member variables are not accessible from outside the class it is hard to mock these fields. In this post we will discuss that how to mock a private member with Mockito while writing test in an spring boot application.
You can watch the YouTube Video here:
Let’s say we have SampleServiceImpl
class that uses ObjectMapper instance which it gets fro SpringServiceConfig class.
@Component
public class SampleServiceImpl {
private ObjectMapper objectMapper = SpringServiceConfig.objectMapper();
public HttpStatus objectMapperMethod() {
try {
Object testObj = objectMapper.writeValueAsBytes("Some-Text");
} catch (JsonProcessingException e) {
return HttpStatus.BAD_REQUEST;
}
return HttpStatus.OK;
}
}
The SpringServiceConfig
has an static method that provides the instance of objectMapper.
public class SpringServiceConfig {
public static ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
We need to write the test for SampleServiceImpl class.
@SpringBootTest
@ExtendWith(SpringExtension.class)
public class SampleServiceImplTest {
@Autowired
private SampleServiceImpl sampleService;
@Test
public void objectMapperMethodTest() {
HttpStatus httpStatus = sampleService.objectMapperMethod();
}
}
It will not be possible to mock the objectMapper object directly as it is private.
A couple of ways to mock the behaviour is to make some change in the original implementation class:
- Make the class variable public.
- Write a method in the class which acts as a getter of that field.
In both the cases, we have to modify the actual implementation which doesn’t seem right as you are modifying the code just for tests.
A better way can be to use Java’s reflect API. You can read more about it in the official documentation here – java.lang.reflect.Field
It can be done like this:
import java.lang.reflect.Field;
@Autowired
private SampleServiceImpl sampleService;
@Mock
private ObjectMapper objectMapperMock;
@Test
public void objectMapperMethodTest() throws JsonProcessingException, NoSuchFieldException, IllegalAccessException {
Field field = sampleService.getClass().getDeclaredField("objectMapper");
field.setAccessible(true);
field.set(sampleService, objectMapperMock);
when(objectMapperMock.writeValueAsBytes(any())).thenThrow(JsonProcessingException.class);
HttpStatus httpStatus = sampleService.objectMapperMethod();
assertThat(httpStatus).isEqualTo(HttpStatus.BAD_REQUEST);
}
Using the getDeclaredField
we can get the private field ‘objectMapper’ of the class. It can be made accessible using the ‘field.setAccessible(true)
‘, finally the private field can be set with the mocked object ‘objectMapperMock
‘.
You can find the code for this example on BitsToGigs GitHub.
Using the above example we can mock the private objects of class.
Thanks for reading!
In the last post we had discussed about Career and Workplace Hacks: Expert Micro Tips for Success. You can read that post here.
Happy Learning!
Subscribe to the BitsToGigs Newsletter