Как получить исключение JsonProcessingException с помощью Jackson
Возможно, это странный вопрос, но я хотел бы получить немного больше информации о моих тестах, и хотя я закодирован против JsonProcessingException
, я не могу создать полезную нагрузку, которая генерирует это исключение, возможно, потому, что Джексон довольно умный и преобразует все в строку, и даже для плохих строк это касается спецификаций JSON. Моя проблема в том, что Джексон неплохо:)
В основном я хочу получить полезную нагрузку, которая, когда я запускаю это, разбивается на JsonProcessingException
:
String jsonPayload = objectMapper.writeValueAsString(payload);
Я пробовал некоторые вроде:
HashMap<String, String> invalidJSONPayload= new HashMap<>();
invalidJSONPayload.put("021",021);
invalidJSONPayload.put("---",021);
invalidJSONPayload.put("~",021);
Я не суетился с типом, поэтому не стесняйтесь предлагать еще один. Например, пустой объект, бросает JsonMappingException
, и я уже поймаю его.
Ответы
Ответ 1
Вы можете использовать что-то вроде этого:
private static class ClassThatJacksonCannotSerialize {
private final ClassThatJacksonCannotSerialize self = this;
@Override
public String toString() {
return self.getClass().getName();
}
}
В результате получается JsonProcessingException
с сообщением Direct self-reference leading to cycle (through reference chain: ClassThatJacksonCannotSerialize["self"])
Ответ 2
Я хотел сделать то же самое, и в конце концов достиг этого, используя "шпионскую" функцию Mockito, которая оборачивает реальный объект фиктивным объектом. Все вызовы фиктивного объекта перенаправляются на реальный объект, кроме тех, которые вы пытаетесь имитировать. Например:
ObjectMapper om = Mockito.spy(new ObjectMapper());
Mockito.when( om.writeValueAsString(ErrorObject.class)).thenThrow(new JsonProcessingException("") {});
Все использования om
будут обрабатываться базовым экземпляром ErrorObject
до тех пор, пока не будет передан экземпляр ErrorObject
, после чего будет JsonProcessingException
.
Новое JsonProcessingException
создается как анонимный класс, так как это защищенный класс, и может быть создан только подкласс.
Ответ 3
следуя @Mike.Mathieson ответ
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
обратите внимание, что этот тест не будет работать, если ObjectMapper настроен на отключение SerializationFeature.FAIL_ON_EMPTY_BEANS
, например
new ObjectMapper()
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.writeValueAsString(new Object());
Ответ 4
Для меня, если класс не имеет общедоступных полей/методов writeValueAsString будет вызывать исключение JsonMappingException (для класса не найден сериализатор)
private static class ClassThatJacksonCannotSerialize {}
private void forceProcessingException() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(value);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
Ответ 5
Создание ответа Лиама, издевательствование метода toString()
с циклом также заставляет Джексона сломаться.
@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: Это проще, чем это. Mockito mock всегда будет бросать его. o.o;;
Ответ 6
Попытка смоделировать с использованием mock(ObjectMapper.class)
неизменно приведет к тому, что проверенное исключение недопустимо для этого метода! так как невозможно выбросить проверенное исключение (JsonProcessingException
расширяет IOException
). Создание самообращающегося объекта значения, как и другие предложенные ответы, может быть слишком сложным для многих случаев и выглядит как хак.
Самый простой способ, который я нашел, - это расширить ObjectMapper
, а затем использовать его в своем методе тестирования. Вы должны передать подкласс в SUT
@Test
public void buildJsonSwallowsJsonProcessingException() {
class MyObjectMapper extends ObjectMapper {
@Override
public String writeValueAsString(Object value)
throws com.fasterxml.jackson.core.JsonProcessingException {
throw new com.fasterxml.jackson.core.JsonProcessingException("Forced error") {};
}
}
ObjectMapper objectMapper = new MyObjectMapper();
SUTBean sutbean = new SUTBean(objectMapper);
sutbean.testMethod();
assertTrue(expected, actual);
}
Ответ 7
на всякий случай это может кому-то помочь, когда я проходил модульное тестирование для JsonProcessingException, я продолжал получать эту ошибку:
JsonProcessingException has protected access in com.fasterxml.jackson...
это был мой код
// error is on the below line
JsonProcessingException e = new JsonProcessingException("borked");
doThrow(e).when(classMock).methodToMock(any(), any());
я узнал, что мне просто нужно добавить "{}" как таковой
JsonProcessingException e = new JsonProcessingException("borked") {};