I have a @JsonTest test case which doesn't find a @Configuration class containing a Jackson2ObjectMapperBuilderCustomizer bean, and so the test fails. I can fix this with an @Import(...). Is there a way to make the @JsonTest find my configuration automatically, or is an @Import expected and the only way?
Context:
Using Spring Boot Starter Parent v. 2.5.3.
My application needs to use ISO-8601 basic formatting for timestamps, which I have configured via Jackson2ObjectMapperBuilderCustomizer as follows:
@Configuration
public class ObjectMapperConfig {
  @Bean
  public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
    return builder -> {
      builder.dateFormat(new StdDateFormat().withColonInTimeZone(false));
    };
  }
}
I wrote a small test to confirm that the ObjectMapper formats dates the expected way. However, @JsonTest does not discover my @Configuration with the customizations, so the test fails unless I explicitly @Import(ObjectMapperConfig.class):
@JsonTest
@Import(ObjectMapperConfig.class) // This is required!
public class ObjectMapperConfigTest {
  @Autowired ObjectMapper mapper;
  @Test
  public void dateFormat() throws Exception {
    var input = Date.from(Instant.ofEpochMilli(0));
    var actual = mapper.writeValueAsString(input);
    // Write all dates in ISO-8601 Basic (not extended) format.
    // Timezones should be formatted +0000 instead of +00:00
    assertEquals("\"1970-01-01T00:00:00.000+0000\"", actual);
  }
}
My understanding of @JsonTest is that it only discovers @JsonComponent annotations, so it would ignore normal @Configuration, which means (for me) it doesn't actually test the Json serialization layer. This answer suggests what I am doing should work, but that does not seem to be the case. Is using an @Import correct, or should I annotate my configuration otherwise? Based on the documentation, it seems inappropriate to use @JsonComponent instead of @Configuration, and the @JsonTest documentation doesn't seem to comment on my scenario. Advice is appreciated. Thanks!
The below approach works for me as of Spring Boot 2.5.12:
import com.fasterxml.jackson.annotation.JsonInclude;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
/**
 * This customizer is annotated with @JsonComponent and hence is used both for production and @JsonTest tests.
 * More details <a href="https://stackoverflow.com/questions/68730482/spring-jsontest-does-not-respect-jackson2objectmapperbuildercustomizer-customiz">here</a>
 */
@JsonComponent
public class JacksonCustomizer implements Jackson2ObjectMapperBuilderCustomizer {
    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        jacksonObjectMapperBuilder.serializationInclusion(JsonInclude.Include.NON_NULL);
    }
}
As much as I personally prefer to use @Configuration + @Bean, I had to refrain to @JsonComponent here because @Import seems to be more error-prone in the long run.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With