The code for my usecase is below:
My class:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class MyClass {
public String getString() {
// object need mocking
ObjectMapper mapper = new ObjectMapper()
try {
// method need mocking
return mapper.writeValueAsString(List.of("1", "2"));
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
Test code:
@Test
public void test_get_string() throws Exception {
ObjectMapper mapper = Mockito.mock(ObjectMapper.class);
Mockito.when(mapper.writeValueAsString(Mockito.anyList()))
.thenThrow(JsonProcessingException.class);
Assertions.assertThrows(RuntimeException.class, () -> {
new MyClass().getString();
});
// -> failed
// Expected RuntimeException but nothing was thrown
}
I want to mock the ObjectMapper and make it throw JsonProcessingException on writeValueAsString method call, but the test keeps failing as if it doesn't use my mocked mapper at all. But if I make the mapper a property of MyClass and mock it, then the test passes.
public class MyClass {
// make mapper a property
private ObjectMapper mapper;
public MyClass(ObjectMapper mapper) {
this.mapper = mapper;
}
public String getString() {
try {
return mapper.writeValueAsString(List.of("1", "2"));
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test_get_string() throws Exception {
ObjectMapper mapper = Mockito.mock(ObjectMapper.class);
Mockito.when(mapper.writeValueAsString(Mockito.anyList()))
.thenThrow(JsonProcessingException.class);
Assertions.assertThrows(RuntimeException.class, () -> {
// pass mapper on creating object
new MyClass(mapper).getString();
}); // -> success
}
In case I don't want to make mapper a property of my class, how should I properly mock it ?
You can't mock a local variable declared in a method using Mockito. You can make
ObjectMappera property of your classMyClass. But if you don't want to do that, the other option is to add a protected method in yourMyClassthat returns an instance ofObjectMapperThen in your test case, you can
spyyour class and stub this new method to return a mockedObjectMapperas shown below: