### Question:
InstantDeserializer extends StdScalarDeserializer<Instant> { @Override public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { try { String text = p.readValueAs(String.class); return text == null ? null : converter.convert(text); } catch (Exception e) { throw new JsonParseException(p, "Could not parse node as instant", e); } } InstantDeserializer(Converter<String, Instant> converter); @Override Instant deserialize(JsonParser p, DeserializationContext ctxt);  }### Answer:
@Test void should_deserialize_string_as_instant() throws IOException { var input = "20190101123456789"; var expected = Instant.parse("2019-01-01T12:34:56.789Z"); given(parser.readValueAs(String.class)).willReturn(input); given(converter.convert(input)).willReturn(expected); var actual = deserializer.deserialize(parser, ctx); assertThat(actual).isEqualTo(expected); verify(parser).readValueAs(String.class); verify(converter).convert(input); }
@Test void should_deserialize_null_as_null() throws IOException { given(parser.readValueAs(String.class)).willReturn(null); var actual = deserializer.deserialize(parser, ctx); assertThat(actual).isNull(); verify(parser).readValueAs(String.class); verify(converter, never()).convert(any()); }
@Test void should_throw_IOE_when_input_invalid() throws IOException { var error = new JsonParseException(parser, "not really"); given(parser.readValueAs(String.class)).willThrow(error); assertThatThrownBy(() -> deserializer.deserialize(parser, ctx)) .isInstanceOf(JsonParseException.class) .hasMessage("Could not parse node as instant") .hasRootCause(error); verify(parser).readValueAs(String.class); }