/* * Copyright 2012-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.boot.autoconfigure.http; import java.util.Arrays; import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import org.junit.After; import org.junit.Test; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; import org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration; import org.springframework.hateoas.ResourceSupport; import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; import static org.assertj.core.api.Assertions.assertThat; /** * Tests for {@link HttpMessageConvertersAutoConfiguration}. * * @author Dave Syer * @author Oliver Gierke * @author David Liu * @author Andy Wilkinson * @author Sebastien Deleuze */ public class HttpMessageConvertersAutoConfigurationTests { private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); @After public void close() { if (this.context != null) { this.context.close(); } } @Test public void noObjectMapperMeansNoConverter() throws Exception { this.context.register(HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertThat(this.context.getBeansOfType(ObjectMapper.class)).isEmpty(); assertThat(this.context.getBeansOfType(MappingJackson2HttpMessageConverter.class)) .isEmpty(); assertThat( this.context.getBeansOfType(MappingJackson2XmlHttpMessageConverter.class)) .isEmpty(); } @Test public void defaultJacksonConverter() throws Exception { this.context.register(JacksonObjectMapperConfig.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertConverterBeanExists(MappingJackson2HttpMessageConverter.class, "mappingJackson2HttpMessageConverter"); assertConverterBeanRegisteredWithHttpMessageConverters( MappingJackson2HttpMessageConverter.class); } @Test public void defaultJacksonConvertersWithBuilder() throws Exception { this.context.register(JacksonObjectMapperBuilderConfig.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertConverterBeanExists(MappingJackson2HttpMessageConverter.class, "mappingJackson2HttpMessageConverter"); assertConverterBeanExists(MappingJackson2XmlHttpMessageConverter.class, "mappingJackson2XmlHttpMessageConverter"); assertConverterBeanRegisteredWithHttpMessageConverters( MappingJackson2HttpMessageConverter.class); assertConverterBeanRegisteredWithHttpMessageConverters( MappingJackson2XmlHttpMessageConverter.class); } @Test public void customJacksonConverter() throws Exception { this.context.register(JacksonObjectMapperConfig.class, JacksonConverterConfig.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertConverterBeanExists(MappingJackson2HttpMessageConverter.class, "customJacksonMessageConverter"); } @Test public void noGson() throws Exception { this.context.register(HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertThat(this.context.getBeansOfType(Gson.class).isEmpty()).isTrue(); assertThat(this.context.getBeansOfType(GsonHttpMessageConverter.class).isEmpty()) .isTrue(); } @Test public void defaultGsonConverter() throws Exception { this.context.register(GsonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertConverterBeanExists(GsonHttpMessageConverter.class, "gsonHttpMessageConverter"); assertConverterBeanRegisteredWithHttpMessageConverters( GsonHttpMessageConverter.class); } @Test public void jacksonIsPreferredByDefaultWhenBothGsonAndJacksonAreAvailable() { this.context.register(GsonAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertConverterBeanExists(MappingJackson2HttpMessageConverter.class, "mappingJackson2HttpMessageConverter"); assertConverterBeanRegisteredWithHttpMessageConverters( MappingJackson2HttpMessageConverter.class); assertThat(this.context.getBeansOfType(GsonHttpMessageConverter.class)).isEmpty(); } @Test public void gsonCanBePreferredWhenBothGsonAndJacksonAreAvailable() { this.context.register(GsonAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class); EnvironmentTestUtils.addEnvironment(this.context, "spring.http.converters.preferred-json-mapper:gson"); this.context.refresh(); assertConverterBeanExists(GsonHttpMessageConverter.class, "gsonHttpMessageConverter"); assertConverterBeanRegisteredWithHttpMessageConverters( GsonHttpMessageConverter.class); assertThat(this.context.getBeansOfType(MappingJackson2HttpMessageConverter.class)) .isEmpty(); } @Test public void customGsonConverter() throws Exception { this.context.register(GsonAutoConfiguration.class, GsonConverterConfig.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertConverterBeanExists(GsonHttpMessageConverter.class, "customGsonMessageConverter"); assertConverterBeanRegisteredWithHttpMessageConverters( GsonHttpMessageConverter.class); } @Test public void defaultStringConverter() throws Exception { this.context.register(HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertConverterBeanExists(StringHttpMessageConverter.class, "stringHttpMessageConverter"); assertConverterBeanRegisteredWithHttpMessageConverters( StringHttpMessageConverter.class); } @Test public void customStringConverter() throws Exception { this.context.register(StringConverterConfig.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertConverterBeanExists(StringHttpMessageConverter.class, "customStringMessageConverter"); assertConverterBeanRegisteredWithHttpMessageConverters( StringHttpMessageConverter.class); } @Test public void typeConstrainedConverterDoesNotPreventAutoConfigurationOfJacksonConverter() throws Exception { this.context.register(JacksonObjectMapperBuilderConfig.class, TypeConstrainedConverterConfiguration.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); BeanDefinition beanDefinition = this.context .getBeanDefinition("mappingJackson2HttpMessageConverter"); assertThat(beanDefinition.getFactoryBeanName()).isEqualTo( MappingJackson2HttpMessageConverterConfiguration.class.getName()); } @Test public void typeConstrainedConverterFromSpringDataDoesNotPreventAutoConfigurationOfJacksonConverter() throws Exception { this.context.register(JacksonObjectMapperBuilderConfig.class, RepositoryRestMvcConfiguration.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); BeanDefinition beanDefinition = this.context .getBeanDefinition("mappingJackson2HttpMessageConverter"); assertThat(beanDefinition.getFactoryBeanName()).isEqualTo( MappingJackson2HttpMessageConverterConfiguration.class.getName()); } private void assertConverterBeanExists(Class<?> type, String beanName) { assertThat(this.context.getBeansOfType(type)).hasSize(1); List<String> beanNames = Arrays.asList(this.context.getBeanDefinitionNames()); assertThat(beanNames).contains(beanName); } private void assertConverterBeanRegisteredWithHttpMessageConverters(Class<?> type) { Object converter = this.context.getBean(type); HttpMessageConverters converters = this.context .getBean(HttpMessageConverters.class); assertThat(converters.getConverters().contains(converter)).isTrue(); } @Configuration protected static class JacksonObjectMapperConfig { @Bean public ObjectMapper objectMapper() { return new ObjectMapper(); } } @Configuration protected static class JacksonObjectMapperBuilderConfig { @Bean public ObjectMapper objectMapper() { return new ObjectMapper(); } @Bean public Jackson2ObjectMapperBuilder builder() { return new Jackson2ObjectMapperBuilder(); } } @Configuration protected static class JacksonConverterConfig { @Bean public MappingJackson2HttpMessageConverter customJacksonMessageConverter( ObjectMapper objectMapper) { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(objectMapper); return converter; } } @Configuration protected static class GsonConverterConfig { @Bean public GsonHttpMessageConverter customGsonMessageConverter(Gson gson) { GsonHttpMessageConverter converter = new GsonHttpMessageConverter(); converter.setGson(gson); return converter; } } @Configuration protected static class StringConverterConfig { @Bean public StringHttpMessageConverter customStringMessageConverter() { return new StringHttpMessageConverter(); } } @Configuration protected static class TypeConstrainedConverterConfiguration { @Bean public TypeConstrainedMappingJackson2HttpMessageConverter typeConstrainedConverter() { return new TypeConstrainedMappingJackson2HttpMessageConverter( ResourceSupport.class); } } }