package org.springframework.cloud.client.loadbalancer; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import java.io.IOException; import java.net.URI; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Random; import lombok.SneakyThrows; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; /** * @author Ryan Baxter */ public abstract class AbstractLoadBalancerAutoConfigurationTests { @Test public void restTemplateGetsLoadBalancerInterceptor() { ConfigurableApplicationContext context = init(OneRestTemplate.class); final Map<String, RestTemplate> restTemplates = context .getBeansOfType(RestTemplate.class); assertThat(restTemplates, is(notNullValue())); assertThat(restTemplates.values(), hasSize(1)); RestTemplate restTemplate = restTemplates.values().iterator().next(); assertThat(restTemplate, is(notNullValue())); assertLoadBalanced(restTemplate); } protected abstract void assertLoadBalanced(RestTemplate restTemplate); @Test public void multipleRestTemplates() { ConfigurableApplicationContext context = init(TwoRestTemplates.class); final Map<String, RestTemplate> restTemplates = context .getBeansOfType(RestTemplate.class); assertThat(restTemplates, is(notNullValue())); Collection<RestTemplate> templates = restTemplates.values(); assertThat(templates, hasSize(2)); TwoRestTemplates.Two two = context.getBean(TwoRestTemplates.Two.class); assertThat(two.loadBalanced, is(notNullValue())); assertLoadBalanced(two.loadBalanced); assertThat(two.nonLoadBalanced, is(notNullValue())); assertThat(two.nonLoadBalanced.getInterceptors(), is(empty())); } protected ConfigurableApplicationContext init(Class<?> config) { return new SpringApplicationBuilder().web(false) .properties("spring.aop.proxyTargetClass=true") .sources(config, LoadBalancerAutoConfiguration.class).run(); } @Configuration protected static class OneRestTemplate { @LoadBalanced @Bean RestTemplate loadBalancedRestTemplate() { return new RestTemplate(); } @Bean LoadBalancerClient loadBalancerClient() { return new NoopLoadBalancerClient(); } @Bean LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory() { return new LoadBalancedRetryPolicyFactory.NeverRetryFactory();} } @Configuration protected static class TwoRestTemplates { @Primary @Bean RestTemplate restTemplate() { return new RestTemplate(); } @LoadBalanced @Bean RestTemplate loadBalancedRestTemplate() { return new RestTemplate(); } @Bean LoadBalancerClient loadBalancerClient() { return new NoopLoadBalancerClient(); } @Bean LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory() { return new LoadBalancedRetryPolicyFactory.NeverRetryFactory();} @Configuration protected static class Two { @Autowired RestTemplate nonLoadBalanced; @Autowired @LoadBalanced RestTemplate loadBalanced; } } private static class NoopLoadBalancerClient implements LoadBalancerClient { private final Random random = new Random(); @Override public ServiceInstance choose(String serviceId) { return new DefaultServiceInstance(serviceId, serviceId, this.random.nextInt(40000), false); } @Override @SneakyThrows public <T> T execute(String serviceId, LoadBalancerRequest<T> request) { return request.apply(choose(serviceId)); } @Override @SneakyThrows public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException { return request.apply(choose(serviceId)); } @Override public URI reconstructURI(ServiceInstance instance, URI original) { return DefaultServiceInstance.getUri(instance); } } }