C'est peut-être une question étrange, mais j'aimerais en fait obtenir une couverture un peu plus longue sur mes tests et bien que j'ai codé avec une variable JsonProcessingException
, je ne peux pas créer de charge utile générant cette exception, peut-être parce que Jackson est assez intelligent et convertit tout en chaîne. , et même pour les mauvaises chaînes, il tourne autour des spécifications JSON. Mon problème est que Jackson est très bon :)
En gros, je veux une charge utile qui, quand je lance ceci, rompt avec JsonProcessingException
:
String jsonPayload = objectMapper.writeValueAsString(payload);
J'ai essayé certains comme:
HashMap<String, String> invalidJSONPayload= new HashMap<>();
invalidJSONPayload.put("021",021);
invalidJSONPayload.put("---",021);
invalidJSONPayload.put("~",021);
Je ne suis pas gêné par le type, alors n'hésitez pas à en suggérer un autre. Un objet vide, par exemple, jette JsonMappingException
et j'attrape déjà celui-ci également.
Je voulais faire la même chose et finalement y arriver en utilisant la fonction "espion" de Mockito, qui enveloppe un objet réel avec un objet fictif. Tous les appels à l'objet simulé sont transférés à l'objet réel, à l'exception de ceux que vous essayez de simuler. Par exemple:
ObjectMapper om = Mockito.spy(new ObjectMapper());
Mockito.when( om.writeValueAsString(ErrorObject.class)).thenThrow(new JsonProcessingException("") {});
Toutes les utilisations de om
seront gérées par l'instance ObjectMapper sous-jacente jusqu'à ce qu'une instance de ErrorObject
soit transmise, auquel moment la JsonProcessingException
sera levée.
NewJsonProcessingException
est créé en tant que classe anonyme, car il s'agit d'une classe protégée et seule une sous-classe peut être instanciée.
Vous pouvez utiliser quelque chose comme ceci:
private static class ClassThatJacksonCannotSerialize {
private final ClassThatJacksonCannotSerialize self = this;
@Override
public String toString() {
return self.getClass().getName();
}
}
Ce qui donne une JsonProcessingException
avec le message Direct self-reference leading to cycle (through reference chain: ClassThatJacksonCannotSerialize["self"])
Pour moi, si une classe n'a pas de champs/méthodes publics, writeValueAsString lève une exception JsonMappingException (aucun sérialiseur n'a été trouvé pour la classe ...)
private static class ClassThatJacksonCannotSerialize {}
private void forceProcessingException() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(value);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
S'appuyant sur la réponse de Liam, se moquer de la méthode toString()
avec un cycle provoque également la rupture de Jackson.
@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: C'est beaucoup plus facile que ça. Un simulacre de Mockito le jettera toujours. o.o ;;
suite à @ Mike.Mathieson répondre
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());
}
}
notez que ce test ne fonctionnera pas si ObjectMapper a été configuré pour désactiver SerializationFeature.FAIL_ON_EMPTY_BEANS
, par exemple.
new ObjectMapper()
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.writeValueAsString(new Object());
Essayer de simuler avec mock(ObjectMapper.class)
entraînera invariablement/ L'exception Checked n'est pas valide pour cette méthode! car il n’est pas possible de lancer une exception vérifiée (JsonProcessingException
extend IOException
). Créer un objet de valeur à référence automatique comme les autres réponses suggérées pourrait être trop compliqué dans de nombreux cas et ressembler à un hack.
Le moyen le plus simple que j'ai trouvé est d'étendre la variable ObjectMapper
, puis de l'utiliser dans votre méthode de test. Vous devriez passer la sous-classe à 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);
}