Might be a strange question but indeed I would like to achieve a a bit more coverage on my tests and although I coded against a JsonProcessingException
I can\'t
Building off of Liam's answer, mocking the toString()
method with a cycle also causes Jackson to break.
@Test
public void forceJsonParseException() {
try {
Object mockItem = mock(Object.class);
when(mockItem.toString()).thenReturn(mockItem.getClass().getName());
new ObjectMapper().writeValueAsString(mockItem);
fail("did not throw JsonProcessingException");
} catch (JsonProcessingException e) {
//pass
}
}
EDIT: It's way easier than that. A Mockito mock will always throw it. o.o;;
For me, if a class has no public
fields/methods, writeValueAsString
will throw a JsonMappingException
(no serializer found for class...
)
private static class ClassThatJacksonCannotSerialize {}
private void forceProcessingException() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(value);
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
I wanted to do the same thing, and eventually accomplished it by using the Mockito "spy" function, which wraps a real object with a mock object. All calls to the mock object get forwarded to the real object, except those you are trying to mock. For example:
ObjectMapper om = Mockito.spy(new ObjectMapper());
Mockito.when( om.writeValueAsString(ErrorObject.class)).thenThrow(new JsonProcessingException("") {});
All usages of om
will be handled by the underlying ObjectMapper instance until an instance of ErrorObject
gets passed in, at which point the JsonProcessingException
will be thrown.
The newJsonProcessingException
is created as an anonymous class, as it is a protected class and only a sub-class can be instantiated.
just in case this may help someone, when i was unit testing for a JsonProcessingException i kept getting this error:
JsonProcessingException has protected access in com.fasterxml.jackson...
this was my code
// error is on the below line
JsonProcessingException e = new JsonProcessingException("borked");
doThrow(e).when(classMock).methodToMock(any(), any());
i found out i just needed to add "{}" as such
JsonProcessingException e = new JsonProcessingException("borked") {};
following on @Mike.Mathieson answer
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
public class JacksonTest {
@Test(expected = JsonProcessingException.class)
// actually throws an InvalidDefinitionException (which extends JsonProcessingException)
public void encodeThrowsException() throws JsonProcessingException {
new ObjectMapper().writeValueAsString(new Object());
}
}
https://fasterxml.github.io/jackson-databind/javadoc/2.9/com/fasterxml/jackson/databind/exc/InvalidDefinitionException.html
note that this test won't work if the ObjectMapper have been configured to disable SerializationFeature.FAIL_ON_EMPTY_BEANS
, e.g.
new ObjectMapper()
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.writeValueAsString(new Object());
You could use something like this:
private static class ClassThatJacksonCannotSerialize {
private final ClassThatJacksonCannotSerialize self = this;
@Override
public String toString() {
return self.getClass().getName();
}
}
Which results in a JsonProcessingException
with message Direct self-reference leading to cycle (through reference chain: ClassThatJacksonCannotSerialize["self"])