Configure TestRestTemplate using builder

Update SpringBootTestContextCustomizer to create the TestRestTemplate
using the RestTemplateBuilder whenever possible.

Fixes gh-5509
pull/6080/merge
Phillip Webb 9 years ago
parent e1d74627f5
commit 433f5e7930

@ -16,11 +16,19 @@
package org.springframework.boot.test.context; package org.springframework.boot.test.context;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.test.web.client.LocalHostUriTemplateHandler; import org.springframework.boot.test.web.client.LocalHostUriTemplateHandler;
import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.env.Environment;
import org.springframework.test.context.ContextCustomizer; import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.MergedContextConfiguration; import org.springframework.test.context.MergedContextConfiguration;
@ -38,12 +46,24 @@ class SpringBootTestContextCustomizer implements ContextCustomizer {
SpringBootTest annotation = AnnotatedElementUtils.getMergedAnnotation( SpringBootTest annotation = AnnotatedElementUtils.getMergedAnnotation(
mergedContextConfiguration.getTestClass(), SpringBootTest.class); mergedContextConfiguration.getTestClass(), SpringBootTest.class);
if (annotation.webEnvironment().isEmbedded()) { if (annotation.webEnvironment().isEmbedded()) {
Object restTemplate = TestRestTemplateFactory registerTestRestTemplate(context);
.createRestTemplate(context.getEnvironment());
context.getBeanFactory().registerSingleton("testRestTemplate", restTemplate);
} }
} }
private void registerTestRestTemplate(ConfigurableApplicationContext context) {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
if (beanFactory instanceof BeanDefinitionRegistry) {
registerTestRestTemplate(context, (BeanDefinitionRegistry) context);
}
}
private void registerTestRestTemplate(ConfigurableApplicationContext context,
BeanDefinitionRegistry registry) {
registry.registerBeanDefinition("testRestTemplate",
new RootBeanDefinition(TestRestTemplateFactory.class));
}
@Override @Override
public int hashCode() { public int hashCode() {
return getClass().hashCode(); return getClass().hashCode();
@ -57,13 +77,47 @@ class SpringBootTestContextCustomizer implements ContextCustomizer {
return true; return true;
} }
// Inner class to avoid references to web classes that may not be on the classpath /**
private static class TestRestTemplateFactory { * {@link FactoryBean} used to create a configure a {@link TestRestTemplate}.
*/
public static class TestRestTemplateFactory
implements FactoryBean<TestRestTemplate>, ApplicationContextAware {
private TestRestTemplate object;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
RestTemplateBuilder builder = getRestTemplateBuilder(applicationContext);
TestRestTemplate template = new TestRestTemplate(builder.build());
template.setUriTemplateHandler(
new LocalHostUriTemplateHandler(applicationContext.getEnvironment()));
this.object = template;
}
private RestTemplateBuilder getRestTemplateBuilder(
ApplicationContext applicationContext) {
try {
return applicationContext.getBean(RestTemplateBuilder.class);
}
catch (NoSuchBeanDefinitionException ex) {
return new RestTemplateBuilder();
}
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public Class<?> getObjectType() {
return TestRestTemplate.class;
}
private static TestRestTemplate createRestTemplate(Environment environment) { @Override
TestRestTemplate template = new TestRestTemplate(); public TestRestTemplate getObject() throws Exception {
template.setUriTemplateHandler(new LocalHostUriTemplateHandler(environment)); return this.object;
return template;
} }
} }

@ -91,30 +91,22 @@ public class TestRestTemplate {
*/ */
public TestRestTemplate(String username, String password, public TestRestTemplate(String username, String password,
HttpClientOption... httpClientOptions) { HttpClientOption... httpClientOptions) {
this.restTemplate = createRestTemplate(username, password, httpClientOptions); this(new RestTemplate(), username, password, httpClientOptions);
} }
/** public TestRestTemplate(RestTemplate restTemplate) {
* Factory method used to create the underlying {@link RestTemplate}. this(restTemplate, null, null);
* @param username the username to use (or {@code null}) }
* @param password the password (or {@code null})
* @param httpClientOptions client options to use if the Apache HTTP Client is used public TestRestTemplate(RestTemplate restTemplate, String username, String password,
* @return the delegate {@link RestTemplate}
*/
protected RestTemplate createRestTemplate(String username, String password,
HttpClientOption... httpClientOptions) { HttpClientOption... httpClientOptions) {
RestTemplate restTemplate = new RestTemplate(); Assert.notNull(restTemplate, "RestTemplate must not be null");
if (ClassUtils.isPresent("org.apache.http.client.config.RequestConfig", null)) { if (ClassUtils.isPresent("org.apache.http.client.config.RequestConfig", null)) {
restTemplate.setRequestFactory( restTemplate.setRequestFactory(
new CustomHttpComponentsClientHttpRequestFactory(httpClientOptions)); new CustomHttpComponentsClientHttpRequestFactory(httpClientOptions));
} }
addAuthentication(restTemplate, username, password); addAuthentication(restTemplate, username, password);
restTemplate.setErrorHandler(new NoOpResponseErrorHandler()); restTemplate.setErrorHandler(new NoOpResponseErrorHandler());
return restTemplate;
}
public TestRestTemplate(RestTemplate restTemplate) {
Assert.notNull(restTemplate, "RestTemplate must not be null");
this.restTemplate = restTemplate; this.restTemplate = restTemplate;
} }

@ -60,6 +60,10 @@ public abstract class AbstractSpringBootTestEmbeddedWebEnvironmentTests {
@Autowired @Autowired
private TestRestTemplate restTemplate; private TestRestTemplate restTemplate;
public TestRestTemplate getRestTemplate() {
return this.restTemplate;
}
@Test @Test
public void runAndTestHttpEndpoint() { public void runAndTestHttpEndpoint() {
assertThat(this.port).isNotEqualTo(8080).isNotEqualTo(0); assertThat(this.port).isNotEqualTo(8080).isNotEqualTo(0);

@ -16,15 +16,21 @@
package org.springframework.boot.test.context; package org.springframework.boot.test.context;
import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Tests for {@link SpringBootTest} configured with {@link WebEnvironment#RANDOM_PORT}. * Tests for {@link SpringBootTest} configured with {@link WebEnvironment#RANDOM_PORT}.
* *
@ -37,11 +43,28 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
public class SpringBootTestWebEnvironmentRandomPortTests public class SpringBootTestWebEnvironmentRandomPortTests
extends AbstractSpringBootTestEmbeddedWebEnvironmentTests { extends AbstractSpringBootTestEmbeddedWebEnvironmentTests {
@Test
public void testRestTemplateShouldUseBuilder() throws Exception {
assertThat(getRestTemplate().getRestTemplate().getMessageConverters())
.hasAtLeastOneElementOfType(MyConverter.class);
}
@Configuration @Configuration
@EnableWebMvc @EnableWebMvc
@RestController @RestController
protected static class Config extends AbstractConfig { protected static class Config extends AbstractConfig {
@Bean
public RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder()
.additionalMessageConverters(new MyConverter());
}
}
private static class MyConverter extends StringHttpMessageConverter {
} }
} }

Loading…
Cancel
Save