1

I have a method in a class called "HttpResponseHelper" that I am trying to Unit Test when it throws a JsonProcessingException, but I was having difficulties getting it do so:

 private static void populateHTTPResponseWithData(ObjectNode httpResponse)
    {
        ObjectMapper mapper = new ObjectMapper();
        responseMapData.keySet().forEach(item -> {
            try
            {
                httpResponse.put(item, mapper.writeValueAsString(responseMapData.get(item)));
            }
            catch (JsonProcessingException e)
            {
                LOGGER.error("Json Processing Exception", e);
            }
        });
    }

The httpResponse argument is type ObjectNode (Jackson library), and then inside the method body a mapper object is created from the ObjectMapper class.

The resonseMapData is a ConcurrentHashMap> from a class called "MessageProcessResults". It looks like here its looping through the keySet and inserting a String for the Key Value pair inside of the httpResponse argument.

I tried using mockito on mapper to return a malformed JSON, but it looks like it writes the value as a String and passes each time.

Does anyone have any suggestions or is there a simple way to do this? Thank you for taking the time to read this question and possibly help me :D

ennth
  • 1,698
  • 5
  • 31
  • 63
  • 1
    This method never throws a `JsonProcessingException`, it catches it and logs the result only, if you were to put `throw e` in your catch block it would throw it aswell, but it would not proceed processing other items in your `responseMapData` when an exception occurs. – Mark Feb 13 '20 at 20:14
  • I'm not sure why you need to test it; I assume just to get 100% coverage of the catch block, but you presumably aren't going to test that the logging occurred. It might be better not to worry about it. But you should inject the ObjectMapper instead of creating one, and then you can inject a mock mapper in your test and have it throw when writeValueAsString is called. – David Conrad Feb 13 '20 at 20:22

3 Answers3

1

You can also extend JsonProcessingException for your tests:

private static class MockJsonProcessingException extends JsonProcessingException {
  public MockJsonProcessingException(String message) {
    super(message);
  }
}

And then in your test:

var exception = new MockJsonProcessingException("Because of protected constructors");
when(objectMapper.writeValueAsString(thing)).thenThrow(exception);

EDIT: Note this assumes you're using dependency injection and injecting a mock ObjectMapper into your object, as is necessary to make this case testable.

hackerly
  • 11
  • 2
0

The @HarryQ answer wont work as JsonProcessingException has a package protected constructor.

For those methods that throw this you can use InputCoercionException. It extends from JsonProcesssingException and allows something like, ugly, yeah I know, but it works:

when(mockObjectMapper.writeValueAsString(any())).thenThrow(new InputCoercionException(null, "my mock exception", null, null));
theINtoy
  • 3,388
  • 2
  • 37
  • 60
-1

When you are doing unit test, you don't focus on how the underlying code would create an exception, but how your code deal with such an exception. In that regards, you can mock the ObjectNode object, and ask it to throw an exception whenever put method is called.

 @Test
public void someTest(){
    Object mockObject = Mockito.mock(ObjectNode.class);
    Mockito.when(mockObject.put()).thenThrow(new JsonProcessingException ("my mock exception"));
    functionUndertest(mockObject); //this is where you inject your mock function. In your case you are expecting a error message to be printed.
}
HarryQ
  • 1,281
  • 2
  • 10
  • 25
  • 1
    This wont work as JsonProcessingException has a package protected constructor. For those methods that throw this you can use InputCoercionException. It extends from JsonProcesssingException and allows something like. Ugly, yeah I know, but it works: when(mockObjectMapper.writeValueAsString(any())).thenThrow(new InputCoercionException(null, "my mock exception", null, null)); – theINtoy Jan 04 '21 at 14:48