/* * 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.web.client; import java.util.Collections; import java.util.Set; import org.apache.http.client.config.RequestConfig; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.springframework.http.client.BufferingClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.client.support.BasicAuthorizationInterceptor; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.ResourceHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriTemplateHandler; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; /** * Tests for {@link RestTemplateBuilder}. * * @author Stephane Nicoll * @author Phillip Webb * @author Andy Wilkinson */ public class RestTemplateBuilderTests { @Rule public ExpectedException thrown = ExpectedException.none(); private RestTemplateBuilder builder = new RestTemplateBuilder(); @Mock private HttpMessageConverter<Object> messageConverter; @Mock private ClientHttpRequestInterceptor interceptor; @Before public void setup() { MockitoAnnotations.initMocks(this); } @Test public void createWhenCustomizersAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("Customizers must not be null"); RestTemplateCustomizer[] customizers = null; new RestTemplateBuilder(customizers); } @Test public void createWithCustomizersShouldApplyCustomizers() throws Exception { RestTemplateCustomizer customizer = mock(RestTemplateCustomizer.class); RestTemplate template = new RestTemplateBuilder(customizer).build(); verify(customizer).customize(template); } @Test public void buildShouldDetectRequestFactory() throws Exception { RestTemplate restTemplate = this.builder.build(); assertThat(restTemplate.getRequestFactory()) .isInstanceOf(HttpComponentsClientHttpRequestFactory.class); } @Test public void detectRequestFactoryWhenFalseShouldDisableDetection() throws Exception { RestTemplate restTemplate = this.builder.detectRequestFactory(false).build(); assertThat(restTemplate.getRequestFactory()) .isInstanceOf(SimpleClientHttpRequestFactory.class); } @Test public void rootUriShouldApply() throws Exception { RestTemplate restTemplate = this.builder.rootUri("http://example.com").build(); MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build(); server.expect(requestTo("http://example.com/hello")).andRespond(withSuccess()); restTemplate.getForEntity("/hello", String.class); server.verify(); } @Test public void rootUriShouldApplyAfterUriTemplateHandler() throws Exception { UriTemplateHandler uriTemplateHandler = mock(UriTemplateHandler.class); RestTemplate template = this.builder.uriTemplateHandler(uriTemplateHandler) .rootUri("http://example.com").build(); UriTemplateHandler handler = template.getUriTemplateHandler(); handler.expand("/hello"); assertThat(handler).isInstanceOf(RootUriTemplateHandler.class); verify(uriTemplateHandler).expand("http://example.com/hello"); } @Test public void messageConvertersWhenConvertersAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("MessageConverters must not be null"); this.builder.messageConverters((HttpMessageConverter<?>[]) null); } @Test public void messageConvertersCollectionWhenConvertersAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("MessageConverters must not be null"); this.builder.messageConverters((Set<HttpMessageConverter<?>>) null); } @Test public void messageConvertersShouldApply() throws Exception { RestTemplate template = this.builder.messageConverters(this.messageConverter) .build(); assertThat(template.getMessageConverters()).containsOnly(this.messageConverter); } @Test public void messageConvertersShouldReplaceExisting() throws Exception { RestTemplate template = this.builder .messageConverters(new ResourceHttpMessageConverter()) .messageConverters(Collections.singleton(this.messageConverter)).build(); assertThat(template.getMessageConverters()).containsOnly(this.messageConverter); } @Test public void additionalMessageConvertersWhenConvertersAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("MessageConverters must not be null"); this.builder.additionalMessageConverters((HttpMessageConverter<?>[]) null); } @Test public void additionalMessageConvertersCollectionWhenConvertersAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("MessageConverters must not be null"); this.builder.additionalMessageConverters((Set<HttpMessageConverter<?>>) null); } @Test public void additionalMessageConvertersShouldAddToExisting() throws Exception { HttpMessageConverter<?> resourceConverter = new ResourceHttpMessageConverter(); RestTemplate template = this.builder.messageConverters(resourceConverter) .additionalMessageConverters(this.messageConverter).build(); assertThat(template.getMessageConverters()).containsOnly(resourceConverter, this.messageConverter); } @Test public void defaultMessageConvertersShouldSetDefaultList() throws Exception { RestTemplate template = new RestTemplate( Collections.<HttpMessageConverter<?>>singletonList( new StringHttpMessageConverter())); this.builder.defaultMessageConverters().configure(template); assertThat(template.getMessageConverters()) .hasSameSizeAs(new RestTemplate().getMessageConverters()); } @Test public void defaultMessageConvertersShouldClearExisting() throws Exception { RestTemplate template = new RestTemplate( Collections.<HttpMessageConverter<?>>singletonList( new StringHttpMessageConverter())); this.builder.additionalMessageConverters(this.messageConverter) .defaultMessageConverters().configure(template); assertThat(template.getMessageConverters()) .hasSameSizeAs(new RestTemplate().getMessageConverters()); } @Test public void interceptorsWhenInterceptorsAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("interceptors must not be null"); this.builder.interceptors((ClientHttpRequestInterceptor[]) null); } @Test public void interceptorsCollectionWhenInterceptorsAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("interceptors must not be null"); this.builder.interceptors((Set<ClientHttpRequestInterceptor>) null); } @Test public void interceptorsShouldApply() throws Exception { RestTemplate template = this.builder.interceptors(this.interceptor).build(); assertThat(template.getInterceptors()).containsOnly(this.interceptor); } @Test public void interceptorsShouldReplaceExisting() throws Exception { RestTemplate template = this.builder .interceptors(mock(ClientHttpRequestInterceptor.class)) .interceptors(Collections.singleton(this.interceptor)).build(); assertThat(template.getInterceptors()).containsOnly(this.interceptor); } @Test public void additionalInterceptorsWhenInterceptorsAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("interceptors must not be null"); this.builder.additionalInterceptors((ClientHttpRequestInterceptor[]) null); } @Test public void additionalInterceptorsCollectionWhenInterceptorsAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("interceptors must not be null"); this.builder.additionalInterceptors((Set<ClientHttpRequestInterceptor>) null); } @Test public void additionalInterceptorsShouldAddToExisting() throws Exception { ClientHttpRequestInterceptor interceptor = mock( ClientHttpRequestInterceptor.class); RestTemplate template = this.builder.interceptors(interceptor) .additionalInterceptors(this.interceptor).build(); assertThat(template.getInterceptors()).containsOnly(interceptor, this.interceptor); } @Test public void requestFactoryClassWhenFactoryIsNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("RequestFactory must not be null"); this.builder.requestFactory((Class<ClientHttpRequestFactory>) null); } @Test public void requestFactoryClassShouldApply() throws Exception { RestTemplate template = this.builder .requestFactory(SimpleClientHttpRequestFactory.class).build(); assertThat(template.getRequestFactory()) .isInstanceOf(SimpleClientHttpRequestFactory.class); } @Test public void requestFactoryPackagePrivateClassShouldApply() throws Exception { RestTemplate template = this.builder .requestFactory(TestClientHttpRequestFactory.class).build(); assertThat(template.getRequestFactory()) .isInstanceOf(TestClientHttpRequestFactory.class); } @Test public void requestFactoryWhenFactoryIsNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("RequestFactory must not be null"); this.builder.requestFactory((ClientHttpRequestFactory) null); } @Test public void requestFactoryShouldApply() throws Exception { ClientHttpRequestFactory requestFactory = mock(ClientHttpRequestFactory.class); RestTemplate template = this.builder.requestFactory(requestFactory).build(); assertThat(template.getRequestFactory()).isSameAs(requestFactory); } @Test public void uriTemplateHandlerWhenHandlerIsNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("UriTemplateHandler must not be null"); this.builder.uriTemplateHandler(null); } @Test public void uriTemplateHandlerShouldApply() throws Exception { UriTemplateHandler uriTemplateHandler = mock(UriTemplateHandler.class); RestTemplate template = this.builder.uriTemplateHandler(uriTemplateHandler) .build(); assertThat(template.getUriTemplateHandler()).isSameAs(uriTemplateHandler); } @Test public void errorHandlerWhenHandlerIsNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("ErrorHandler must not be null"); this.builder.errorHandler(null); } @Test public void errorHandlerShouldApply() throws Exception { ResponseErrorHandler errorHandler = mock(ResponseErrorHandler.class); RestTemplate template = this.builder.errorHandler(errorHandler).build(); assertThat(template.getErrorHandler()).isSameAs(errorHandler); } @Test public void basicAuthorizationShouldApply() throws Exception { RestTemplate template = this.builder.basicAuthorization("spring", "boot").build(); ClientHttpRequestInterceptor interceptor = template.getInterceptors().get(0); assertThat(interceptor).isInstanceOf(BasicAuthorizationInterceptor.class); assertThat(interceptor).extracting("username").containsExactly("spring"); assertThat(interceptor).extracting("password").containsExactly("boot"); } @Test public void customizersWhenCustomizersAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("RestTemplateCustomizers must not be null"); this.builder.customizers((RestTemplateCustomizer[]) null); } @Test public void customizersCollectionWhenCustomizersAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("RestTemplateCustomizers must not be null"); this.builder.customizers((Set<RestTemplateCustomizer>) null); } @Test public void customizersShouldApply() throws Exception { RestTemplateCustomizer customizer = mock(RestTemplateCustomizer.class); RestTemplate template = this.builder.customizers(customizer).build(); verify(customizer).customize(template); } @Test public void customizersShouldBeAppliedLast() throws Exception { RestTemplate template = spy(new RestTemplate()); this.builder.additionalCustomizers(new RestTemplateCustomizer() { @Override public void customize(RestTemplate restTemplate) { verify(restTemplate).setRequestFactory((ClientHttpRequestFactory) any()); } }); this.builder.configure(template); } @Test public void customizersShouldReplaceExisting() throws Exception { RestTemplateCustomizer customizer1 = mock(RestTemplateCustomizer.class); RestTemplateCustomizer customizer2 = mock(RestTemplateCustomizer.class); RestTemplate template = this.builder.customizers(customizer1) .customizers(Collections.singleton(customizer2)).build(); verifyZeroInteractions(customizer1); verify(customizer2).customize(template); } @Test public void additionalCustomizersWhenCustomizersAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("RestTemplateCustomizers must not be null"); this.builder.additionalCustomizers((RestTemplateCustomizer[]) null); } @Test public void additionalCustomizersCollectionWhenCustomizersAreNullShouldThrowException() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("RestTemplateCustomizers must not be null"); this.builder.additionalCustomizers((Set<RestTemplateCustomizer>) null); } @Test public void additionalCustomizersShouldAddToExisting() throws Exception { RestTemplateCustomizer customizer1 = mock(RestTemplateCustomizer.class); RestTemplateCustomizer customizer2 = mock(RestTemplateCustomizer.class); RestTemplate template = this.builder.customizers(customizer1) .additionalCustomizers(customizer2).build(); verify(customizer1).customize(template); verify(customizer2).customize(template); } @Test public void buildShouldReturnRestTemplate() throws Exception { RestTemplate template = this.builder.build(); assertThat(template.getClass()).isEqualTo(RestTemplate.class); } @Test public void buildClassShouldReturnClassInstance() throws Exception { RestTemplateSubclass template = this.builder.build(RestTemplateSubclass.class); assertThat(template.getClass()).isEqualTo(RestTemplateSubclass.class); } @Test public void configureShouldApply() throws Exception { RestTemplate template = new RestTemplate(); this.builder.configure(template); assertThat(template.getRequestFactory()) .isInstanceOf(HttpComponentsClientHttpRequestFactory.class); } @Test public void connectTimeoutCanBeConfiguredOnHttpComponentsRequestFactory() { ClientHttpRequestFactory requestFactory = this.builder .requestFactory(HttpComponentsClientHttpRequestFactory.class) .setConnectTimeout(1234).build().getRequestFactory(); assertThat(((RequestConfig) ReflectionTestUtils.getField(requestFactory, "requestConfig")).getConnectTimeout()).isEqualTo(1234); } @Test public void readTimeoutCanBeConfiguredOnHttpComponentsRequestFactory() { ClientHttpRequestFactory requestFactory = this.builder .requestFactory(HttpComponentsClientHttpRequestFactory.class) .setReadTimeout(1234).build().getRequestFactory(); assertThat(((RequestConfig) ReflectionTestUtils.getField(requestFactory, "requestConfig")).getSocketTimeout()).isEqualTo(1234); } @Test public void connectTimeoutCanBeConfiguredOnSimpleRequestFactory() { ClientHttpRequestFactory requestFactory = this.builder .requestFactory(SimpleClientHttpRequestFactory.class) .setConnectTimeout(1234).build().getRequestFactory(); assertThat(ReflectionTestUtils.getField(requestFactory, "connectTimeout")) .isEqualTo(1234); } @Test public void readTimeoutCanBeConfiguredOnSimpleRequestFactory() { ClientHttpRequestFactory requestFactory = this.builder .requestFactory(SimpleClientHttpRequestFactory.class).setReadTimeout(1234) .build().getRequestFactory(); assertThat(ReflectionTestUtils.getField(requestFactory, "readTimeout")) .isEqualTo(1234); } @Test public void connectTimeoutCanBeConfiguredOnOkHttp3RequestFactory() { ClientHttpRequestFactory requestFactory = this.builder .requestFactory(OkHttp3ClientHttpRequestFactory.class) .setConnectTimeout(1234).build().getRequestFactory(); assertThat(ReflectionTestUtils.getField( ReflectionTestUtils.getField(requestFactory, "client"), "connectTimeout")) .isEqualTo(1234); } @Test public void readTimeoutCanBeConfiguredOnOkHttp3RequestFactory() { ClientHttpRequestFactory requestFactory = this.builder .requestFactory(OkHttp3ClientHttpRequestFactory.class) .setReadTimeout(1234).build().getRequestFactory(); assertThat(ReflectionTestUtils.getField( ReflectionTestUtils.getField(requestFactory, "client"), "readTimeout")) .isEqualTo(1234); } @Test public void connectTimeoutCanBeConfiguredOnAWrappedRequestFactory() { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); this.builder.requestFactory(new BufferingClientHttpRequestFactory(requestFactory)) .setConnectTimeout(1234).build(); assertThat(ReflectionTestUtils.getField(requestFactory, "connectTimeout")) .isEqualTo(1234); } @Test public void readTimeoutCanBeConfiguredOnAWrappedRequestFactory() { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); this.builder.requestFactory(new BufferingClientHttpRequestFactory(requestFactory)) .setReadTimeout(1234).build(); assertThat(ReflectionTestUtils.getField(requestFactory, "readTimeout")) .isEqualTo(1234); } @Test public void unwrappingDoesNotAffectRequestFactoryThatIsSetOnTheBuiltTemplate() { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); RestTemplate template = this.builder .requestFactory(new BufferingClientHttpRequestFactory(requestFactory)) .build(); assertThat(template.getRequestFactory()) .isInstanceOf(BufferingClientHttpRequestFactory.class); } public static class RestTemplateSubclass extends RestTemplate { } static class TestClientHttpRequestFactory extends SimpleClientHttpRequestFactory { } }