Cómo obtener una JsonProcessingException usando Jackson

5 minutos de lectura

Puede ser una pregunta extraña, pero de hecho me gustaría lograr un poco más de cobertura en mis pruebas y, aunque codifiqué contra un JsonProcessingException No puedo crear una carga útil que genere esta excepción, tal vez porque Jackson es bastante inteligente y convierte todo en una cadena, e incluso para las cadenas malas se ajusta a las especificaciones de JSON. Mi problema es que Jackson es bastante bueno 🙂

Básicamente, quiero una carga útil que cuando ejecute esto, se rompa con JsonProcessingException:

String jsonPayload = objectMapper.writeValueAsString(payload);

He probado algunos como:

HashMap<String, String> invalidJSONPayload= new HashMap<>();

invalidJSONPayload.put("021",021);
invalidJSONPayload.put("---",021);
invalidJSONPayload.put("~",021);

No estoy preocupado con el tipo, así que no dude en sugerir otro. Un objeto vacío, por ejemplo, arroja JsonMappingException y ya cogí ese también.

  • Bueno, puedes burlarte de un ObjectMapper y hacer que arroje esa excepción ya que ObjectMapper no es definitivo

    – fge

    3 de noviembre de 2014 a las 14:30

  • ¿No sería burlarse de la prueba en sí? Me gustaría reproducir un escenario que de hecho puede ocurrir en el contexto de la aplicación en ejecución. ¿Quizás uno no existe? Si es así, ¿por qué la excepción? Gracias por la respuesta.

    – bitoiu

    3 de noviembre de 2014 a las 15:31

  • Bueno, pensé que querías probar el comportamiento de tu código en caso de que se produjera esta excepción, por lo que sugerí esto

    – fge

    3 de noviembre de 2014 a las 15:42

  • Supongo que tiene sentido, y si no surgen otras sugerencias, también podría hacerlo. Simplemente pensé que debería haber una manera de producir esa excepción con algún tipo de objeto aleatorio que no se analizaría correctamente en JSON. Maldito Jackson y es un análisis inteligente.

    – bitoiu

    3 de noviembre de 2014 a las 16:31

  • Podrías intentar darle algo de XML… 🙂

    – sorbete

    6 de noviembre de 2014 a las 1:38

Avatar de usuario de Lee Passey
Lee Passey

Quería hacer lo mismo y finalmente lo logré usando la función “espía” de Mockito, que envuelve un objeto real con un objeto simulado. Todas las llamadas al objeto simulado se reenvían al objeto real, excepto aquellas que intenta simular. Por ejemplo:

ObjectMapper om = Mockito.spy(new ObjectMapper());
Mockito.when( om.writeValueAsString(ErrorObject.class)).thenThrow(new JsonProcessingException("") {});

Todos los usos de om será manejado por la instancia de ObjectMapper subyacente hasta que una instancia de ErrorObject se pasa adentro, en cuyo punto el JsonProcessingException será arrojado.

El nuevoJsonProcessingException se crea como una clase anónima, ya que es una clase protegida y solo se puede instanciar una subclase.

  • Suponiendo que el objeto de carga útil tenga métodos de captación y establecimiento públicos, simplemente podría usar espiar el objeto de carga útil y luego hacer que uno de los captadores devuelva un valor nulo. Carga útil payloadSpy = Mockito.spy (carga útil); Mockito.doReturn(null).when(payloadSpy).getField(); String jsonPayload = objectMapper.writeValueAsString(payloadSpy);

    – pilotg2

    2 oct 2015 a las 17:14


  • esto arrojará Checked exception is invalid for this method! y no funciona

    – senseiwu

    9 de diciembre de 2018 a las 14:38

  • El constructor JsonProcessingException tiene un modificador de acceso de protección. Entonces, no se puede crear llamando new JsonProcessingException("")

    – hemin

    24 de marzo de 2021 a las 3:22

Avatar de usuario de Hazel T
avellana t

Partiendo de la respuesta de Liam, burlándose de la toString() El método con un ciclo también hace que Jackson se rompa.

@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
    }
}

EDITAR: Es mucho más fácil que eso. Un simulacro de Mockito siempre lo tirará. ooo;;

  • Trabajó para mi. Dado que el elemento simulado no se puede serializar, se lanza la excepción si usa este elemento simulado como un parámetro de su método probado. no necesitas el when cláusula por cierto.

    –Julián Feniou

    21 de octubre de 2020 a las 9:46

Podrías usar algo como esto:

private static class ClassThatJacksonCannotSerialize {
    private final ClassThatJacksonCannotSerialize self = this;

    @Override
    public String toString() {
        return self.getClass().getName();
   }
}

Lo cual resulta en un JsonProcessingException con mensaje Direct self-reference leading to cycle (through reference chain: ClassThatJacksonCannotSerialize["self"])

  • Con 2.9, no pude replicar con el toString anular, tuve que hacer esto: private static class WillNotSerialize { public WillNotSerialize getSelf() { return this; } }

    – nathansizemore

    12 ago. 2019 a las 19:30

siguiendo la respuesta de @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

tenga en cuenta que esta prueba no funcionará si ObjectMapper se configuró para deshabilitar SerializationFeature.FAIL_ON_EMPTY_BEANSp.ej

new ObjectMapper()
    .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
    .writeValueAsString(new Object());

Avatar de usuario de Mike Mathieson
Mike Mathieson

Para mí, si una clase no tiene public campos/métodos, writeValueAsString lanzará un 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);
    }
}

  • Funciona, gracias. Usé esto en mi prueba para cubrir la cláusula de lanzamiento :+1:

    – Dmitri Popov

    30 de junio de 2020 a las 13:58

avatar de usuario de heug
hola

en caso de que esto pueda ayudar a alguien, cuando estaba realizando pruebas unitarias para una JsonProcessingException, seguía recibiendo este error:

JsonProcessingException has protected access in com.fasterxml.jackson...

este era mi codigo

// error is on the below line
JsonProcessingException e = new JsonProcessingException("borked");

doThrow(e).when(classMock).methodToMock(any(), any());

descubrí que solo necesitaba agregar “{}” como tal

JsonProcessingException e = new JsonProcessingException("borked") {};

  • Funciona, gracias. Usé esto en mi prueba para cubrir la cláusula de lanzamiento :+1:

    – Dmitri Popov

    30 de junio de 2020 a las 13:58

Avatar de usuario de SHZ
SHZ

Puede obtener una JsonProcessingException si asigna dos campos a la misma propiedad.

class InvalidObject {
    @JsonProperty("s")
    private String x = "value1";
    
    @JsonProperty("s")
    private String y = "value2";
}

El mensaje de excepción es “Múltiples campos que representan la propiedad “s”:…”

  • Esta es una solución súper simple y debe marcarse como respuesta. ¡Funciona de maravilla! Gracias.

    – Táner

    13 oct a las 14:20


¿Ha sido útil esta solución?