在 Spring Boot Spock 规范中使用 RestTemplate 和定制的 Jackson

Using RestTemplate in Spring Boot Spock specification with customized Jackson

我有一个 Spring 启动应用程序,它使用自定义的 Jackson ObjectMapper,我想在测试期间使用相同的自定义映射器。我使用了spring boot的自动注册Module Bean的方法,像这样:

@Configuration
public class JacksonConfig {
    @Bean
    public Module jodaMoneyJackson() {
        SimpleModule jodaMoneyModule = new SimpleModule();

        jodaMoneyModule.addDeserializer(Money.class, new JsonDeserializer<Money>() {
            @Override
            public Money deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                return Money.parse(p.getText());
            }
        });

        jodaMoneyModule.addSerializer(Money.class, new ToStringSerializer());

        return jodaMoneyModule;
    }

    @Bean public Module googleGuavaJackson() {
        return new GuavaModule();
    }
}

在我的 spock 测试中,我希望 RestTemplate 使用自动注册自定义模块的 "built-in" Jackson 对象映射器。在实际的应用程序中,它似乎只是自动使用,但在我的测试中没有 类。如何让它适用于我的测试?

我的测试规范大致如下:

@WebIntegrationTest
@ContextConfiguration(loader = SpringApplicationContextLoader, classes = MyApplication)
class SomeTestSpec extends Specification {

    def restTemplate = new RestTemplate()        

    def "test my controller"() {
        given:
        Money expectedTotal = Money.of(CurrencyUnit.USD, 100.00)
        String request = this.class.classLoader.getResource("testInput.json").text

        when:
        def response = restTemplate.postForObject("http://localhost:8080/test", request, SomeClass)

        then:
        response.total == expectedTotal
    }
}

我总是收到 400 Bad Request 响应,在调试时我可以看到这是因为 serialization/deserialization 在内部没有使用我的自定义模块。

作为解决方法,我实例化了自己的对象映射器并手动注册了模块,然后使用来自 RestTemplate 的字符串响应调用 mapper.readValue(),但感觉应该有更好的方法。如有任何意见,我们将不胜感激。

使用由 spock-spring 提供的 Spock Spring 支持,您可以将 ObjectMapper 注入到您的测试规范中:

@WebIntegrationTest
@ContextConfiguration(loader = SpringApplicationContextLoader, classes = MyApplication)
class SomeTestSpec extends Specification {

    @Autowired
    ObjectMapper objectMapper

}