How to unit-test Jackson JsonSerializer and JsonDeserializer

jackson, unit-testing

Solution

JsonSerializer

The example is serialising a `LocalDateTime` but this can replaced by the required type.

@Test
public void serialises_LocalDateTime() throws JsonProcessingException, IOException {
    Writer jsonWriter = new StringWriter();
    JsonGenerator jsonGenerator = new JsonFactory().createGenerator(jsonWriter);
    SerializerProvider serializerProvider = new ObjectMapper().getSerializerProvider();
    new LocalDateTimeJsonSerializer().serialize(LocalDateTime.of(2000, Month.JANUARY, 1, 0, 0), jsonGenerator, serializerProvider);
    jsonGenerator.flush();
    assertThat(jsonWriter.toString(), is(equalTo("\"2000-01-01T00:00:00\"")));
}

JsonDeserializer

The example is deserialising a `Number` but this can replaced by the required type.

    private ObjectMapper mapper;
    private CustomerNumberDeserialiser deserializer;

    @Before
    public void setup() {
        mapper = new ObjectMapper();
        deserializer = new CustomerNumberDeserialiser();
    }

    @Test
    public void floating_point_string_deserialises_to_Double_value() {
        String json = String.format("{\"value\":%s}", "\"1.1\"");
        Number deserialisedNumber = deserialiseNumber(json);
        assertThat(deserialisedNumber, instanceOf(Double.class));
        assertThat(deserialisedNumber, is(equalTo(1.1d)));
    }

    @SneakyThrows({JsonParseException.class, IOException.class})
    private Number deserialiseNumber(String json) {
        InputStream stream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
        JsonParser parser = mapper.getFactory().createParser(stream);
        DeserializationContext ctxt = mapper.getDeserializationContext();
        parser.nextToken();
        parser.nextToken();
        parser.nextToken();
        return deserializer.deserialize(parser, ctxt);
    }

UPDATE

When upgrading to jackson 2.9.3 I received a `NullPointerException` in `DeserializationContext` in `isEnabled(MapperFeature feature)` when deserialising strings to numbers because `new ObjectMapper()` initialises `_config` to `null`.

To get around this, I used this SO answer to spy on the `final` class `DeserializationContext`:

DeserializationContext ctxt = spy(mapper.getDeserializationContext());
doReturn(true).when(ctxt).isEnabled(any(MapperFeature.class));

I feel there must be a better way, so please comment if you have one.

Problem

I've written custom JsonSerializer and JsonDeserializer for my app. Now I want to write some unit-tests for them. How should a clean test case look like? Are there some clean examples out there? (clean means no dependencies to other frameworks or libraries)

Original source

Related problems