Added checkstyle

This commit is contained in:
Marcin Grzejszczak
2019-02-05 18:46:31 +01:00
parent 1f37891ffe
commit c8c7452848
120 changed files with 6686 additions and 4301 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,13 +12,20 @@
* 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.cloud.openfeign;
import feign.Contract;
import feign.Feign;
import feign.Logger;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.optionals.OptionalDecoder;
import feign.slf4j.Slf4jLogger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
@@ -30,14 +37,6 @@ import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import feign.Contract;
import feign.Feign;
import feign.Logger;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.optionals.OptionalDecoder;
import feign.slf4j.Slf4jLogger;
/**
* @author Spencer Gibb
*/
@@ -51,8 +50,7 @@ public class EnableFeignClientsTests {
@Test
public void decoderDefaultCorrect() {
OptionalDecoder.class
.cast(this.feignContext.getInstance("foo", Decoder.class));
OptionalDecoder.class.cast(this.feignContext.getInstance("foo", Decoder.class));
}
@Test
@@ -81,6 +79,7 @@ public class EnableFeignClientsTests {
@Import({ PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class,
FeignAutoConfiguration.class })
protected static class PlainConfiguration {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -25,16 +25,18 @@ import java.util.Collections;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import org.springframework.cloud.openfeign.testclients.TestClient;
import org.springframework.context.ApplicationContext;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Sven Döring
*/
@@ -65,14 +67,14 @@ public class FeignClientBuilderTests {
fieldName);
ReflectionUtils.makeAccessible(field);
final Object value = ReflectionUtils.getField(field, factoryBean);
Assert.assertEquals("Expected value for the field '" + fieldName + "':",
expectedValue, value);
assertThat(value).as("Expected value for the field '" + fieldName + "':")
.isEqualTo(expectedValue);
}
@Before
public void setUp() {
this.applicationContext = Mockito.mock(ApplicationContext.class);
this.feignClientBuilder = new FeignClientBuilder(applicationContext);
this.feignClientBuilder = new FeignClientBuilder(this.applicationContext);
}
@Test
@@ -91,18 +93,18 @@ public class FeignClientBuilderTests {
// on this builder class.
// (2) Or a new field was added and the builder class has to be extended with this
// new field.
Assert.assertThat(methodNames, Matchers.contains("contextId", "decode404", "fallback",
"fallbackFactory", "name", "path", "url"));
assertThat(methodNames).containsExactly("contextId", "decode404", "fallback",
"fallbackFactory", "name", "path", "url");
}
@Test
public void forType_preinitializedBuilder() {
// when:
final FeignClientBuilder.Builder builder = feignClientBuilder
final FeignClientBuilder.Builder builder = this.feignClientBuilder
.forType(FeignClientBuilderTests.class, "TestClient");
// then:
assertFactoryBeanField(builder, "applicationContext", applicationContext);
assertFactoryBeanField(builder, "applicationContext", this.applicationContext);
assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
assertFactoryBeanField(builder, "name", "TestClient");
assertFactoryBeanField(builder, "contextId", "TestClient");
@@ -123,13 +125,13 @@ public class FeignClientBuilderTests {
@Test
public void forType_allFieldsSetOnBuilder() {
// when:
final FeignClientBuilder.Builder builder = feignClientBuilder
final FeignClientBuilder.Builder builder = this.feignClientBuilder
.forType(FeignClientBuilderTests.class, "TestClient").decode404(true)
.fallback(Object.class).fallbackFactory(Object.class).path("Path/")
.url("Url/");
// then:
assertFactoryBeanField(builder, "applicationContext", applicationContext);
assertFactoryBeanField(builder, "applicationContext", this.applicationContext);
assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
assertFactoryBeanField(builder, "name", "TestClient");
@@ -144,16 +146,17 @@ public class FeignClientBuilderTests {
@Test
public void forType_build() {
// given:
Mockito.when(applicationContext.getBean(FeignContext.class))
Mockito.when(this.applicationContext.getBean(FeignContext.class))
.thenThrow(new ClosedFileSystemException()); // throw an unusual exception
// in the
// FeignClientFactoryBean
final FeignClientBuilder.Builder builder = feignClientBuilder
final FeignClientBuilder.Builder builder = this.feignClientBuilder
.forType(TestClient.class, "TestClient");
// expect: 'the build will fail right after calling build() with the mocked
// unusual exception'
thrown.expect(Matchers.isA(ClosedFileSystemException.class));
this.thrown.expect(Matchers.isA(ClosedFileSystemException.class));
builder.build();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -16,16 +16,14 @@
package org.springframework.cloud.openfeign;
import java.util.Arrays;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import java.util.Arrays;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Spencer Gibb
@@ -42,33 +40,43 @@ public class FeignClientFactoryTests {
getSpec("bar", BarConfig.class)));
Foo foo = context.getInstance("foo", Foo.class);
assertThat("foo was null", foo, is(notNullValue()));
assertThat(foo).as("foo was null").isNotNull();
Bar bar = context.getInstance("bar", Bar.class);
assertThat("bar was null", bar, is(notNullValue()));
assertThat(bar).as("bar was null").isNotNull();
Bar foobar = context.getInstance("foo", Bar.class);
assertThat("bar was not null", foobar, is(nullValue()));
assertThat(foobar).as("bar was not null").isNull();
}
private FeignClientSpecification getSpec(String name, Class<?> configClass) {
return new FeignClientSpecification(name, new Class[]{configClass});
return new FeignClientSpecification(name, new Class[] { configClass });
}
static class FooConfig {
@Bean
Foo foo() {
return new Foo();
}
}
static class Foo{}
static class Foo {
}
static class BarConfig {
@Bean
Bar bar() {
return new Bar();
}
}
static class Bar{}
static class Bar {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,31 +12,10 @@
* 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.cloud.openfeign;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import feign.Contract;
import feign.Feign;
import feign.Logger;
@@ -52,6 +31,24 @@ import feign.codec.ErrorDecoder;
import feign.hystrix.HystrixFeign;
import feign.optionals.OptionalDecoder;
import feign.slf4j.Slf4jLogger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Spencer Gibb
@@ -72,8 +69,8 @@ public class FeignClientOverrideDefaultsTests {
@Test
public void clientsAvailable() {
assertNotNull(this.foo);
assertNotNull(this.bar);
assertThat(this.foo).isNotNull();
assertThat(this.bar).isNotNull();
}
@Test
@@ -102,45 +99,62 @@ public class FeignClientOverrideDefaultsTests {
@Test
public void overrideLoggerLevel() {
assertNull(this.context.getInstance("foo", Logger.Level.class));
assertEquals(Logger.Level.HEADERS,
this.context.getInstance("bar", Logger.Level.class));
assertThat(this.context.getInstance("foo", Logger.Level.class)).isNull();
assertThat(this.context.getInstance("bar", Logger.Level.class))
.isEqualTo(Logger.Level.HEADERS);
}
@Test
public void overrideRetryer() {
assertEquals(Retryer.NEVER_RETRY, this.context.getInstance("foo", Retryer.class));
assertThat(this.context.getInstance("foo", Retryer.class))
.isEqualTo(Retryer.NEVER_RETRY);
Retryer.Default.class.cast(this.context.getInstance("bar", Retryer.class));
}
@Test
public void overrideErrorDecoder() {
assertNull(this.context.getInstance("foo", ErrorDecoder.class));
assertThat(this.context.getInstance("foo", ErrorDecoder.class)).isNull();
ErrorDecoder.Default.class
.cast(this.context.getInstance("bar", ErrorDecoder.class));
}
@Test
public void overrideBuilder() {
HystrixFeign.Builder.class.cast(this.context.getInstance("foo", Feign.Builder.class));
Feign.Builder.class
.cast(this.context.getInstance("bar", Feign.Builder.class));
HystrixFeign.Builder.class
.cast(this.context.getInstance("foo", Feign.Builder.class));
Feign.Builder.class.cast(this.context.getInstance("bar", Feign.Builder.class));
}
@Test
public void overrideRequestOptions() {
assertNull(this.context.getInstance("foo", Request.Options.class));
assertThat(this.context.getInstance("foo", Request.Options.class)).isNull();
Request.Options options = this.context.getInstance("bar", Request.Options.class);
assertEquals(1, options.connectTimeoutMillis());
assertEquals(1, options.readTimeoutMillis());
assertThat(options.connectTimeoutMillis()).isEqualTo(1);
assertThat(options.readTimeoutMillis()).isEqualTo(1);
}
@Test
public void addRequestInterceptor() {
assertEquals(1,
this.context.getInstances("foo", RequestInterceptor.class).size());
assertEquals(2,
this.context.getInstances("bar", RequestInterceptor.class).size());
assertThat(this.context.getInstances("foo", RequestInterceptor.class).size())
.isEqualTo(1);
assertThat(this.context.getInstances("bar", RequestInterceptor.class).size())
.isEqualTo(2);
}
@FeignClient(name = "foo", url = "http://foo", configuration = FooConfiguration.class)
interface FooClient {
@RequestLine("GET /")
String get();
}
@FeignClient(name = "bar", url = "http://bar", configuration = BarConfiguration.class)
interface BarClient {
@RequestMapping(value = "/", method = RequestMethod.GET)
String get();
}
@Configuration
@@ -148,6 +162,7 @@ public class FeignClientOverrideDefaultsTests {
@Import({ PropertyPlaceholderAutoConfiguration.class, ArchaiusAutoConfiguration.class,
FeignAutoConfiguration.class })
protected static class TestConfiguration {
@Bean
RequestInterceptor defaultRequestInterceptor() {
return new RequestInterceptor() {
@@ -156,16 +171,11 @@ public class FeignClientOverrideDefaultsTests {
}
};
}
}
@FeignClient(name = "foo", url = "http://foo", configuration = FooConfiguration.class)
interface FooClient {
@RequestLine("GET /")
String get();
}
public static class FooConfiguration {
@Bean
public Decoder feignDecoder() {
return new Decoder.Default();
@@ -190,15 +200,11 @@ public class FeignClientOverrideDefaultsTests {
public Feign.Builder feignBuilder() {
return HystrixFeign.builder();
}
}
@FeignClient(name = "bar", url = "http://bar", configuration = BarConfiguration.class)
interface BarClient {
@RequestMapping(value = "/", method = RequestMethod.GET)
String get();
}
public static class BarConfiguration {
@Bean
Logger.Level feignLevel() {
return Logger.Level.HEADERS;
@@ -223,5 +229,7 @@ public class FeignClientOverrideDefaultsTests {
RequestInterceptor feignRequestInterceptor() {
return new BasicAuthRequestInterceptor("user", "pass");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -37,7 +37,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
@@ -52,14 +51,15 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Eko Kurniawan Khannedy
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = FeignClientUsingPropertiesTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@SpringBootTest(classes = FeignClientUsingPropertiesTests.Application.class, webEnvironment = RANDOM_PORT)
@TestPropertySource("classpath:feign-properties.properties")
@DirtiesContext
public class FeignClientUsingPropertiesTests {
@@ -80,38 +80,41 @@ public class FeignClientUsingPropertiesTests {
private FeignClientFactoryBean formFactoryBean;
public FeignClientUsingPropertiesTests() {
fooFactoryBean = new FeignClientFactoryBean();
fooFactoryBean.setContextId("foo");
fooFactoryBean.setType(FeignClientFactoryBean.class);
this.fooFactoryBean = new FeignClientFactoryBean();
this.fooFactoryBean.setContextId("foo");
this.fooFactoryBean.setType(FeignClientFactoryBean.class);
barFactoryBean = new FeignClientFactoryBean();
barFactoryBean.setContextId("bar");
barFactoryBean.setType(FeignClientFactoryBean.class);
this.barFactoryBean = new FeignClientFactoryBean();
this.barFactoryBean.setContextId("bar");
this.barFactoryBean.setType(FeignClientFactoryBean.class);
formFactoryBean = new FeignClientFactoryBean();
formFactoryBean.setContextId("form");
formFactoryBean.setType(FeignClientFactoryBean.class);
this.formFactoryBean = new FeignClientFactoryBean();
this.formFactoryBean.setContextId("form");
this.formFactoryBean.setType(FeignClientFactoryBean.class);
}
public FooClient fooClient() {
fooFactoryBean.setApplicationContext(applicationContext);
return fooFactoryBean.feign(context).target(FooClient.class, "http://localhost:" + this.port);
this.fooFactoryBean.setApplicationContext(this.applicationContext);
return this.fooFactoryBean.feign(this.context).target(FooClient.class,
"http://localhost:" + this.port);
}
public BarClient barClient() {
barFactoryBean.setApplicationContext(applicationContext);
return barFactoryBean.feign(context).target(BarClient.class, "http://localhost:" + this.port);
this.barFactoryBean.setApplicationContext(this.applicationContext);
return this.barFactoryBean.feign(this.context).target(BarClient.class,
"http://localhost:" + this.port);
}
public FormClient formClient() {
formFactoryBean.setApplicationContext(applicationContext);
return formFactoryBean.feign(context).target(FormClient.class, "http://localhost:" + this.port);
this.formFactoryBean.setApplicationContext(this.applicationContext);
return this.formFactoryBean.feign(this.context).target(FormClient.class,
"http://localhost:" + this.port);
}
@Test
public void testFoo() {
String response = fooClient().foo();
assertEquals("OK", response);
assertThat(response).isEqualTo("OK");
}
@Test(expected = RetryableException.class)
@@ -124,25 +127,26 @@ public class FeignClientUsingPropertiesTests {
public void testForm() {
Map<String, String> request = Collections.singletonMap("form", "Data");
String response = formClient().form(request);
assertEquals("Data", response);
assertThat(response).isEqualTo("Data");
}
protected interface FooClient {
@RequestMapping(method = RequestMethod.GET, value = "/foo")
String foo();
}
protected interface BarClient {
@RequestMapping(method = RequestMethod.GET, value = "/bar")
String bar();
}
protected interface FormClient {
@RequestMapping(value = "/form", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@RequestMapping(value = "/form", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
String form(Map<String, String> form);
}
@@ -155,10 +159,11 @@ public class FeignClientUsingPropertiesTests {
@RequestMapping(method = RequestMethod.GET, value = "/foo")
public String foo(HttpServletRequest request) throws IllegalAccessException {
if ("Foo".equals(request.getHeader("Foo")) &&
"Bar".equals(request.getHeader("Bar"))) {
if ("Foo".equals(request.getHeader("Foo"))
&& "Bar".equals(request.getHeader("Bar"))) {
return "OK";
} else {
}
else {
throw new IllegalAccessException("It should has Foo and Bar header");
}
}
@@ -169,8 +174,7 @@ public class FeignClientUsingPropertiesTests {
return "OK";
}
@RequestMapping(value = "/form", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@RequestMapping(value = "/form", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String form(HttpServletRequest request) {
return request.getParameter("form");
}
@@ -178,17 +182,21 @@ public class FeignClientUsingPropertiesTests {
}
public static class FooRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
template.header("Foo", "Foo");
}
}
public static class BarRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
template.header("Bar", "Bar");
}
}
public static class NoRetryer implements Retryer {
@@ -202,24 +210,29 @@ public class FeignClientUsingPropertiesTests {
public Retryer clone() {
return this;
}
}
public static class DefaultErrorDecoder extends ErrorDecoder.Default {
}
public static class FormEncoder implements Encoder {
@Override
public void encode(Object o, Type type, RequestTemplate requestTemplate) throws EncodeException {
public void encode(Object o, Type type, RequestTemplate requestTemplate)
throws EncodeException {
Map<String, String> form = (Map<String, String>) o;
StringBuilder builder = new StringBuilder();
form.forEach((key, value) -> {
builder.append(key + "=" + value + "&");
});
requestTemplate.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
requestTemplate.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_FORM_URLENCODED_VALUE);
requestTemplate.body(Request.Body.bodyTemplate(builder.toString(), UTF_8));
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,7 +12,6 @@
* 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.cloud.openfeign;
@@ -20,6 +19,7 @@ package org.springframework.cloud.openfeign;
import java.util.Collections;
import org.junit.Test;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
@@ -27,8 +27,7 @@ import org.springframework.mock.env.MockEnvironment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Spencer Gibb
@@ -41,7 +40,6 @@ public class FeignClientsRegistrarTests {
testGetName("http://bad_hostname");
}
@Test(expected = IllegalStateException.class)
public void badNameHttpsPrefix() {
testGetName("https://bad_hostname");
@@ -60,19 +58,19 @@ public class FeignClientsRegistrarTests {
@Test
public void goodName() {
String name = testGetName("good-name");
assertThat("name was wrong", name, is("good-name"));
assertThat(name).as("name was wrong").isEqualTo("good-name");
}
@Test
public void goodNameHttpPrefix() {
String name = testGetName("http://good-name");
assertThat("name was wrong", name, is("http://good-name"));
assertThat(name).as("name was wrong").isEqualTo("http://good-name");
}
@Test
public void goodNameHttpsPrefix() {
String name = testGetName("https://goodname");
assertThat("name was wrong", name, is("https://goodname"));
assertThat(name).as("name was wrong").isEqualTo("https://goodname");
}
private String testGetName(String name) {
@@ -81,7 +79,6 @@ public class FeignClientsRegistrarTests {
return registrar.getName(Collections.<String, Object>singletonMap("name", name));
}
@Test(expected = IllegalArgumentException.class)
public void testFallback() {
new AnnotationConfigApplicationContext(FallbackTestConfig.class);
@@ -92,30 +89,35 @@ public class FeignClientsRegistrarTests {
new AnnotationConfigApplicationContext(FallbackFactoryTestConfig.class);
}
@Configuration
@EnableAutoConfiguration
@EnableFeignClients(clients = { FeignClientsRegistrarTests.FallbackClient.class})
protected static class FallbackTestConfig {
}
@FeignClient(name = "fallbackTestClient", url = "http://localhost:8080/", fallback = FallbackClient.class)
protected interface FallbackClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
String fallbackTest();
}
@Configuration
@EnableAutoConfiguration
@EnableFeignClients(clients = { FeignClientsRegistrarTests.FallbackFactoryClient.class})
protected static class FallbackFactoryTestConfig {
}
@FeignClient(name = "fallbackFactoryTestClient", url = "http://localhost:8081/", fallbackFactory = FallbackFactoryClient.class)
protected interface FallbackFactoryClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
String fallbackFactoryTest();
}
@Configuration
@EnableAutoConfiguration
@EnableFeignClients(clients = { FeignClientsRegistrarTests.FallbackClient.class })
protected static class FallbackTestConfig {
}
@Configuration
@EnableAutoConfiguration
@EnableFeignClients(clients = {
FeignClientsRegistrarTests.FallbackFactoryClient.class })
protected static class FallbackFactoryTestConfig {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,15 +12,18 @@
* 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.cloud.openfeign;
import java.util.Map;
import feign.Client;
import feign.RequestInterceptor;
import feign.httpclient.ApacheHttpClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -35,10 +38,6 @@ import org.springframework.cloud.test.ModifiedClassPathRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import feign.Client;
import feign.RequestInterceptor;
import feign.httpclient.ApacheHttpClient;
import static org.assertj.core.api.Assertions.assertThat;
/**
@@ -90,7 +89,9 @@ public class FeignCompressionTests {
* a bean here of type ApacheHttpClient so that the configuration will be
* loaded correctly.
*/
return (ApacheHttpClient) client;
return (ApacheHttpClient) this.client;
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,14 +12,16 @@
* 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.cloud.openfeign;
import java.lang.reflect.Field;
import javax.net.ssl.SSLContextSpi;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
import org.apache.http.config.Lookup;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
@@ -28,6 +30,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
@@ -36,8 +39,7 @@ import org.springframework.cloud.test.ModifiedClassPathRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.ReflectionUtils;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Ryan Baxter
@@ -50,8 +52,8 @@ public class FeignHttpClientConfigurationTests {
@Before
public void setUp() {
context = new SpringApplicationBuilder()
.properties("debug=true","feign.httpclient.disableSslValidation=true")
this.context = new SpringApplicationBuilder()
.properties("debug=true", "feign.httpclient.disableSslValidation=true")
.web(WebApplicationType.NONE)
.sources(HttpClientConfiguration.class, FeignAutoConfiguration.class)
.run();
@@ -59,29 +61,38 @@ public class FeignHttpClientConfigurationTests {
@After
public void tearDown() {
if(context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void disableSslTest() throws Exception {
HttpClientConnectionManager connectionManager = context.getBean(HttpClientConnectionManager.class);
Lookup<ConnectionSocketFactory> socketFactoryRegistry = getConnectionSocketFactoryLookup(connectionManager);
assertNotNull(socketFactoryRegistry.lookup("https"));
assertNull(this.getX509TrustManager(socketFactoryRegistry).getAcceptedIssuers());
HttpClientConnectionManager connectionManager = this.context
.getBean(HttpClientConnectionManager.class);
Lookup<ConnectionSocketFactory> socketFactoryRegistry = getConnectionSocketFactoryLookup(
connectionManager);
assertThat(socketFactoryRegistry.lookup("https")).isNotNull();
assertThat(this.getX509TrustManager(socketFactoryRegistry).getAcceptedIssuers())
.isNull();
}
private Lookup<ConnectionSocketFactory> getConnectionSocketFactoryLookup(HttpClientConnectionManager connectionManager) {
DefaultHttpClientConnectionOperator connectionOperator = (DefaultHttpClientConnectionOperator)this.getField(connectionManager, "connectionOperator");
return (Lookup)this.getField(connectionOperator, "socketFactoryRegistry");
private Lookup<ConnectionSocketFactory> getConnectionSocketFactoryLookup(
HttpClientConnectionManager connectionManager) {
DefaultHttpClientConnectionOperator connectionOperator = (DefaultHttpClientConnectionOperator) this
.getField(connectionManager, "connectionOperator");
return (Lookup) this.getField(connectionOperator, "socketFactoryRegistry");
}
private X509TrustManager getX509TrustManager(Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
ConnectionSocketFactory connectionSocketFactory = (ConnectionSocketFactory)socketFactoryRegistry.lookup("https");
SSLSocketFactory sslSocketFactory = (SSLSocketFactory)this.getField(connectionSocketFactory, "socketfactory");
SSLContextSpi sslContext = (SSLContextSpi)this.getField(sslSocketFactory, "context");
return (X509TrustManager)this.getField(sslContext, "trustManager");
private X509TrustManager getX509TrustManager(
Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
ConnectionSocketFactory connectionSocketFactory = (ConnectionSocketFactory) socketFactoryRegistry
.lookup("https");
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) this
.getField(connectionSocketFactory, "socketfactory");
SSLContextSpi sslContext = (SSLContextSpi) this.getField(sslSocketFactory,
"context");
return (X509TrustManager) this.getField(sslContext, "trustManager");
}
protected <T> Object getField(Object target, String name) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,28 +12,25 @@
* 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.cloud.openfeign;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.lang.reflect.Field;
import java.util.Objects;
import feign.Client;
import feign.Feign;
import feign.Target;
import feign.httpclient.ApacheHttpClient;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -46,16 +43,14 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import feign.Client;
import feign.Feign;
import feign.Target;
import feign.httpclient.ApacheHttpClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
/**
* @author Spencer Gibb
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = FeignHttpClientUrlTests.TestConfig.class, webEnvironment = WebEnvironment.DEFINED_PORT, value = {
@SpringBootTest(classes = FeignHttpClientUrlTests.TestConfig.class, webEnvironment = DEFINED_PORT, value = {
"spring.application.name=feignclienturltest", "feign.hystrix.enabled=false",
"feign.okhttp.enabled=false" })
@DirtiesContext
@@ -63,6 +58,15 @@ public class FeignHttpClientUrlTests {
static int port;
@Autowired
BeanUrlClientNoProtocol beanClientNoProtocol;
@Autowired
private UrlClient urlClient;
@Autowired
private BeanUrlClient beanClient;
@BeforeClass
public static void beforeClass() {
port = SocketUtils.findAvailableTcpPort();
@@ -74,37 +78,61 @@ public class FeignHttpClientUrlTests {
System.clearProperty("server.port");
}
@Autowired
private UrlClient urlClient;
@Test
public void testUrlHttpClient() {
assertThat(this.urlClient).as("UrlClient was null").isNotNull();
Hello hello = this.urlClient.getHello();
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match")
.isEqualTo(new Hello("hello world 1"));
}
@Autowired
private BeanUrlClient beanClient;
@Test
public void testBeanUrl() {
Hello hello = this.beanClient.getHello();
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match")
.isEqualTo(new Hello("hello world 1"));
}
@Autowired BeanUrlClientNoProtocol beanClientNoProtocol;
@Test
public void testBeanUrlNoProtocol() {
Hello hello = this.beanClientNoProtocol.getHello();
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match")
.isEqualTo(new Hello("hello world 1"));
}
// this tests that
@FeignClient(name = "localappurl", url = "http://localhost:${server.port}/")
protected interface UrlClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello getHello();
}
@FeignClient(name = "beanappurl", url = "#{SERVER_URL}path")
protected interface BeanUrlClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello getHello();
}
@FeignClient(name = "beanappurlnoprotocol", url = "#{SERVER_URL_NO_PROTOCOL}path")
protected interface BeanUrlClientNoProtocol {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello getHello();
}
@Configuration
@EnableAutoConfiguration
@RestController
@EnableFeignClients(clients = { UrlClient.class, BeanUrlClient.class, BeanUrlClientNoProtocol.class })
@EnableFeignClients(clients = { UrlClient.class, BeanUrlClient.class,
BeanUrlClientNoProtocol.class })
@Import(NoSecurityConfiguration.class)
protected static class TestConfig {
@@ -118,12 +146,12 @@ public class FeignHttpClientUrlTests {
return getHello();
}
@Bean(name="SERVER_URL")
@Bean(name = "SERVER_URL")
public String serverUrl() {
return "http://localhost:" + port + "/";
}
@Bean(name="SERVER_URL_NO_PROTOCOL")
@Bean(name = "SERVER_URL_NO_PROTOCOL")
public String serverUrlNoProtocol() {
return "localhost:" + port + "/";
}
@@ -139,8 +167,8 @@ public class FeignHttpClientUrlTests {
ReflectionUtils.makeAccessible(field);
Client client = (Client) ReflectionUtils.getField(field, feign);
if (target.name().equals("localappurl")) {
assertThat("client was wrong type", client,
is(instanceOf(ApacheHttpClient.class)));
assertThat(client).isInstanceOf(ApacheHttpClient.class)
.as("client was wrong type");
}
return feign.target(target);
}
@@ -149,29 +177,8 @@ public class FeignHttpClientUrlTests {
}
@Test
public void testUrlHttpClient() {
assertNotNull("UrlClient was null", this.urlClient);
Hello hello = this.urlClient.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}
@Test
public void testBeanUrl() {
Hello hello = this.beanClient.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}
@Test
public void testBeanUrlNoProtocol() {
Hello hello = this.beanClientNoProtocol.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}
public static class Hello {
private String message;
public Hello() {
@@ -182,7 +189,7 @@ public class FeignHttpClientUrlTests {
}
public String getMessage() {
return message;
return this.message;
}
public void setMessage(String message) {
@@ -191,15 +198,21 @@ public class FeignHttpClientUrlTests {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Hello that = (Hello) o;
return Objects.equals(message, that.message);
return Objects.equals(this.message, that.message);
}
@Override
public int hashCode() {
return Objects.hash(message);
return Objects.hash(this.message);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016 the original author or authors.
* Copyright 2016-2019 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.
@@ -16,9 +16,8 @@
package org.springframework.cloud.openfeign;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import feign.Logger;
import feign.slf4j.Slf4jLogger;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -26,8 +25,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import feign.Logger;
import feign.slf4j.Slf4jLogger;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Venil Noronha
@@ -36,12 +34,38 @@ public class FeignLoggerFactoryTests {
@Test
public void testDefaultLogger() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleConfiguration1.class);
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
SampleConfiguration1.class);
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
assertNotNull(loggerFactory);
assertThat(loggerFactory).isNotNull();
Logger logger = loggerFactory.create(Object.class);
assertNotNull(logger);
assertTrue(logger instanceof Slf4jLogger);
assertThat(logger).isNotNull();
assertThat(logger instanceof Slf4jLogger).isTrue();
context.close();
}
@Test
public void testCustomLogger() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
SampleConfiguration2.class);
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
assertThat(loggerFactory).isNotNull();
Logger logger = loggerFactory.create(Object.class);
assertThat(logger).isNotNull();
assertThat(logger instanceof LoggerImpl1).isTrue();
context.close();
}
@Test
public void testCustomLoggerFactory() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
SampleConfiguration3.class);
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
assertThat(loggerFactory).isNotNull();
assertThat(loggerFactory instanceof LoggerFactoryImpl).isTrue();
Logger logger = loggerFactory.create(Object.class);
assertThat(logger).isNotNull();
assertThat(logger instanceof LoggerImpl2).isTrue();
context.close();
}
@@ -51,17 +75,6 @@ public class FeignLoggerFactoryTests {
}
@Test
public void testCustomLogger() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleConfiguration2.class);
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
assertNotNull(loggerFactory);
Logger logger = loggerFactory.create(Object.class);
assertNotNull(logger);
assertTrue(logger instanceof LoggerImpl1);
context.close();
}
@Configuration
@Import(FeignClientsConfiguration.class)
protected static class SampleConfiguration2 {
@@ -82,18 +95,6 @@ public class FeignLoggerFactoryTests {
}
@Test
public void testCustomLoggerFactory() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleConfiguration3.class);
FeignLoggerFactory loggerFactory = context.getBean(FeignLoggerFactory.class);
assertNotNull(loggerFactory);
assertTrue(loggerFactory instanceof LoggerFactoryImpl);
Logger logger = loggerFactory.create(Object.class);
assertNotNull(logger);
assertTrue(logger instanceof LoggerImpl2);
context.close();
}
@Configuration
@Import(FeignClientsConfiguration.class)
protected static class SampleConfiguration3 {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,19 +12,20 @@
* 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.cloud.openfeign;
import okhttp3.OkHttpClient;
import java.lang.reflect.Field;
import javax.net.ssl.HostnameVerifier;
import okhttp3.OkHttpClient;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
@@ -34,6 +35,8 @@ import org.springframework.cloud.test.ModifiedClassPathRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Ryan Baxter
*/
@@ -45,23 +48,29 @@ public class FeignOkHttpConfigurationTests {
@Before
public void setUp() {
context = new SpringApplicationBuilder().properties("debug=true","feign.httpclient.disableSslValidation=true",
"feign.okhttp.enabled=true", "feign.httpclient.enabled=false").web(WebApplicationType.NONE)
.sources(HttpClientConfiguration.class, FeignAutoConfiguration.class).run();
this.context = new SpringApplicationBuilder()
.properties("debug=true", "feign.httpclient.disableSslValidation=true",
"feign.okhttp.enabled=true", "feign.httpclient.enabled=false")
.web(WebApplicationType.NONE)
.sources(HttpClientConfiguration.class, FeignAutoConfiguration.class)
.run();
}
@After
public void tearDown() {
if(context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void disableSslTest() throws Exception {
OkHttpClient httpClient = context.getBean(OkHttpClient.class);
HostnameVerifier hostnameVerifier = (HostnameVerifier)this.getField(httpClient, "hostnameVerifier");
Assert.assertTrue(OkHttpClientFactory.TrustAllHostnames.class.isInstance(hostnameVerifier));
OkHttpClient httpClient = this.context.getBean(OkHttpClient.class);
HostnameVerifier hostnameVerifier = (HostnameVerifier) this.getField(httpClient,
"hostnameVerifier");
assertThat(
OkHttpClientFactory.TrustAllHostnames.class.isInstance(hostnameVerifier))
.isTrue();
}
protected <T> Object getField(Object target, String name) {
@@ -70,4 +79,5 @@ public class FeignOkHttpConfigurationTests {
Object value = ReflectionUtils.getField(field, target);
return value;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -23,6 +23,7 @@ import java.util.Objects;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -40,10 +41,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Spencer Gibb
@@ -72,66 +70,73 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
public TestClient testClient(boolean decode404) {
setType(this.getClass());
setDecode404(decode404);
return feign(context).target(TestClient.class, "http://localhost:" + this.port);
return feign(this.context).target(TestClient.class,
"http://localhost:" + this.port);
}
@Test
public void testResponseEntity() {
ResponseEntity<Hello> response = testClient().getHelloResponse();
assertNotNull("response was null", response);
assertEquals("wrong status code", HttpStatus.OK, response.getStatusCode());
assertThat(response).as("response was null").isNotNull();
assertThat(response.getStatusCode()).as("wrong status code")
.isEqualTo(HttpStatus.OK);
Hello hello = response.getBody();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world via response"),
hello);
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match")
.isEqualTo(new Hello("hello world via response"));
}
@Test
public void testSimpleType() {
Hello hello = testClient().getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match")
.isEqualTo(new Hello("hello world 1"));
}
@Test
public void testUserParameterizedTypeDecode() {
List<Hello> hellos = testClient().getHellos();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", new Hello("hello world 1"),
hellos.get(0));
assertThat(hellos).as("hellos was null").isNotNull();
assertThat(hellos.size()).as("hellos was not the right size").isEqualTo(2);
assertThat(hellos.get(0)).as("first hello didn't match")
.isEqualTo(new Hello("hello world 1"));
}
@Test
public void testSimpleParameterizedTypeDecode() {
List<String> hellos = testClient().getHelloStrings();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", "hello world 1", hellos.get(0));
assertThat(hellos).as("hellos was null").isNotNull();
assertThat(hellos.size()).as("hellos was not the right size").isEqualTo(2);
assertThat(hellos.get(0)).as("first hello didn't match")
.isEqualTo("hello world 1");
}
@Test
@SuppressWarnings("unchecked")
public void testWildcardTypeDecode() {
ResponseEntity<?> wildcard = testClient().getWildcard();
assertNotNull("wildcard was null", wildcard);
assertEquals("wrong status code", HttpStatus.OK, wildcard.getStatusCode());
assertThat(wildcard).as("wildcard was null").isNotNull();
assertThat(wildcard.getStatusCode()).as("wrong status code")
.isEqualTo(HttpStatus.OK);
Object wildcardBody = wildcard.getBody();
assertNotNull("wildcardBody was null", wildcardBody);
assertTrue("wildcard not an instance of Map", wildcardBody instanceof Map);
assertThat(wildcardBody).as("wildcardBody was null").isNotNull();
assertThat(wildcardBody instanceof Map).as("wildcard not an instance of Map")
.isTrue();
Map<String, String> hello = (Map<String, String>) wildcardBody;
assertEquals("first hello didn't match", "wildcard", hello.get("message"));
assertThat(hello.get("message")).as("first hello didn't match")
.isEqualTo("wildcard");
}
@Test
public void testResponseEntityVoid() {
ResponseEntity<Void> response = testClient().getHelloVoid();
assertNotNull("response was null", response);
assertThat(response).as("response was null").isNotNull();
List<String> headerVals = response.getHeaders().get("X-test-header");
assertNotNull("headerVals was null", headerVals);
assertEquals("headerVals size was wrong", 1, headerVals.size());
assertThat(headerVals).as("headerVals was null").isNotNull();
assertThat(headerVals.size()).as("headerVals size was wrong").isEqualTo(1);
String header = headerVals.get(0);
assertEquals("header was wrong", "myval", header);
assertThat(header).as("header was wrong").isEqualTo("myval");
}
@Test(expected = RuntimeException.class)
@@ -142,43 +147,12 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
@Test
public void testDecodes404() {
final ResponseEntity<String> response = testClient(true).getNotFound();
assertNotNull("response was null", response);
assertNull("response body was not null", response.getBody());
}
public static class Hello {
private String message;
public Hello() {
}
public Hello(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Hello that = (Hello) o;
return Objects.equals(message, that.message);
}
@Override
public int hashCode() {
return Objects.hash(message);
}
assertThat(response).as("response was null").isNotNull();
assertThat(response.getBody()).as("response body was not null").isNull();
}
protected interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/helloresponse")
ResponseEntity<Hello> getHelloResponse();
@@ -199,6 +173,45 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
@GetMapping("/helloWildcard")
ResponseEntity<?> getWildcard();
}
public static class Hello {
private String message;
public Hello() {
}
public Hello(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Hello that = (Hello) o;
return Objects.equals(this.message, that.message);
}
@Override
public int hashCode() {
return Objects.hash(this.message);
}
}
@Configuration
@@ -247,7 +260,7 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
public ResponseEntity<?> getWildcard() {
return ResponseEntity.ok(new Hello("wildcard"));
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -14,62 +14,64 @@
* limitations under the License.
*/
package org.springframework.cloud.openfeign;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
import org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
import org.springframework.cloud.test.ClassPathExclusions;
import org.springframework.cloud.test.ModifiedClassPathRunner;
import org.springframework.context.ConfigurableApplicationContext;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.core.Is.is;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Ryan Baxter
*/
@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions({"spring-retry-*.jar", "spring-boot-starter-aop-*.jar"})
@ClassPathExclusions({ "spring-retry-*.jar", "spring-boot-starter-aop-*.jar" })
public class SpringRetryDisabledTests {
private ConfigurableApplicationContext context;
@Before
public void setUp() {
context = new SpringApplicationBuilder().web(WebApplicationType.NONE)
.sources(RibbonAutoConfiguration.class, LoadBalancerAutoConfiguration.class, RibbonClientConfiguration.class,
FeignRibbonClientAutoConfiguration.class).run();
this.context = new SpringApplicationBuilder().web(WebApplicationType.NONE)
.sources(RibbonAutoConfiguration.class,
LoadBalancerAutoConfiguration.class,
RibbonClientConfiguration.class,
FeignRibbonClientAutoConfiguration.class)
.run();
}
@After
public void tearDown() {
if(context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void testLoadBalancedRetryFactoryBean() throws Exception {
Map<String, CachingSpringLoadBalancerFactory> lbFactorys = context.getBeansOfType(CachingSpringLoadBalancerFactory.class);
assertThat(lbFactorys.values(), hasSize(1));
FeignLoadBalancer lb =lbFactorys.values().iterator().next().create("foo");
assertThat(lb, instanceOf(FeignLoadBalancer.class));
assertThat(lb, is(not(instanceOf(RetryableFeignLoadBalancer.class))));
Map<String, CachingSpringLoadBalancerFactory> lbFactorys = this.context
.getBeansOfType(CachingSpringLoadBalancerFactory.class);
assertThat(lbFactorys.values()).hasSize(1);
FeignLoadBalancer lb = lbFactorys.values().iterator().next().create("foo");
assertThat(lb).isInstanceOf(FeignLoadBalancer.class);
assertThat(lb).isNotInstanceOf(RetryableFeignLoadBalancer.class);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -17,46 +17,49 @@
package org.springframework.cloud.openfeign;
import java.util.Map;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
import org.springframework.cloud.openfeign.ribbon.RetryableFeignLoadBalancer;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Ryan Baxter
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RibbonAutoConfiguration.class, RibbonClientConfiguration.class, LoadBalancerAutoConfiguration.class,
FeignRibbonClientAutoConfiguration.class, HttpClientConfiguration.class})
@ContextConfiguration(classes = { RibbonAutoConfiguration.class,
RibbonClientConfiguration.class, LoadBalancerAutoConfiguration.class,
FeignRibbonClientAutoConfiguration.class, HttpClientConfiguration.class })
public class SpringRetryEnabledTests implements ApplicationContextAware {
private ApplicationContext context;
@Test
public void testLoadBalancedRetryFactoryBean() throws Exception {
Map<String, CachingSpringLoadBalancerFactory> lbFactorys = context.getBeansOfType(CachingSpringLoadBalancerFactory.class);
assertThat(lbFactorys.values(), Matchers.hasSize(1));
FeignLoadBalancer lb =lbFactorys.values().iterator().next().create("foo");
assertThat(lb, instanceOf(RetryableFeignLoadBalancer.class));
Map<String, CachingSpringLoadBalancerFactory> lbFactorys = this.context
.getBeansOfType(CachingSpringLoadBalancerFactory.class);
assertThat(lbFactorys.values()).hasSize(1);
FeignLoadBalancer lb = lbFactorys.values().iterator().next().create("foo");
assertThat(lb).isInstanceOf(RetryableFeignLoadBalancer.class);
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -23,6 +23,7 @@ import java.util.Objects;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
@@ -42,8 +43,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Dave Syer
@@ -73,6 +73,44 @@ public class FeignClientTests {
@Autowired
private TestClient buildByBuilder;
@Test
public void testAnnotations() {
Map<String, Object> beans = this.context
.getBeansWithAnnotation(FeignClient.class);
assertThat(beans.containsKey(TestClient.class.getName()))
.as("Wrong clients: " + beans).isTrue();
}
@Test
public void testClient() {
assertThat(this.testClient).as("testClient was null").isNotNull();
assertThat(this.extraClient).as("extraClient was null").isNotNull();
assertThat(Proxy.isProxyClass(this.testClient.getClass()))
.as("testClient is not a java Proxy").isTrue();
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.testClient);
assertThat(invocationHandler).as("invocationHandler was null").isNotNull();
}
@Test
public void extraClient() {
assertThat(this.extraClient).as("extraClient was null").isNotNull();
assertThat(Proxy.isProxyClass(this.extraClient.getClass()))
.as("extraClient is not a java Proxy").isTrue();
InvocationHandler invocationHandler = Proxy
.getInvocationHandler(this.extraClient);
assertThat(invocationHandler).as("invocationHandler was null").isNotNull();
}
@Test
public void buildByBuilder() {
assertThat(this.buildByBuilder).as("buildByBuilder was null").isNotNull();
assertThat(Proxy.isProxyClass(this.buildByBuilder.getClass()))
.as("buildByBuilder is not a java Proxy").isTrue();
InvocationHandler invocationHandler = Proxy
.getInvocationHandler(this.buildByBuilder);
assertThat(invocationHandler).as("invocationHandler was null").isNotNull();
}
@Configuration
@EnableAutoConfiguration
@RestController
@@ -82,18 +120,18 @@ public class FeignClientTests {
@Bean("build-by-builder")
public TestClient buildByBuilder(final FeignClientBuilder feignClientBuilder) {
return feignClientBuilder
.forType(TestClient.class, "builderapp")
.build();
return feignClientBuilder.forType(TestClient.class, "builderapp").build();
}
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello() {
return new Hello("hello world 1");
}
}
public static class Hello {
private String message;
public Hello() {
@@ -104,7 +142,7 @@ public class FeignClientTests {
}
public String getMessage() {
return message;
return this.message;
}
public void setMessage(String message) {
@@ -113,56 +151,27 @@ public class FeignClientTests {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Hello that = (Hello) o;
return Objects.equals(message, that.message);
return Objects.equals(this.message, that.message);
}
@Override
public int hashCode() {
return message != null ? message.hashCode() : 0;
return this.message != null ? this.message.hashCode() : 0;
}
}
@Test
public void testAnnotations() {
Map<String, Object> beans = this.context
.getBeansWithAnnotation(FeignClient.class);
assertTrue("Wrong clients: " + beans,
beans.containsKey(TestClient.class.getName()));
}
@Test
public void testClient() {
assertNotNull("testClient was null", this.testClient);
assertNotNull("extraClient was null", this.extraClient);
assertTrue("testClient is not a java Proxy",
Proxy.isProxyClass(this.testClient.getClass()));
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.testClient);
assertNotNull("invocationHandler was null", invocationHandler);
}
@Test
public void extraClient() {
assertNotNull("extraClient was null", this.extraClient);
assertTrue("extraClient is not a java Proxy",
Proxy.isProxyClass(this.extraClient.getClass()));
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.extraClient);
assertNotNull("invocationHandler was null", invocationHandler);
}
@Test
public void buildByBuilder() {
assertNotNull("buildByBuilder was null", this.buildByBuilder);
assertTrue("buildByBuilder is not a java Proxy",
Proxy.isProxyClass(this.buildByBuilder.getClass()));
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.buildByBuilder);
assertNotNull("invocationHandler was null", invocationHandler);
}
@Configuration
public static class TestDefaultFeignConfig {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -23,8 +23,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Primary
@FeignClient(value = "localapp")
@FeignClient("localapp")
public interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello getHello();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -23,6 +23,8 @@ import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(value = "otherapp", qualifier = "uniquequalifier")
public interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello getHello();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -22,7 +22,6 @@ import java.util.List;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -30,11 +29,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.encoding.app.client.InvoiceClient;
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -44,15 +42,15 @@ import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* Tests the response compression.
*
* @author Jakub Narloch
*/
@SpringBootTest(classes = FeignAcceptEncodingTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = {
@SpringBootTest(classes = FeignAcceptEncodingTests.Application.class, webEnvironment = RANDOM_PORT, value = {
"feign.compression.response.enabled=true" })
@RunWith(SpringRunner.class)
@DirtiesContext
@@ -68,10 +66,10 @@ public class FeignAcceptEncodingTests {
final ResponseEntity<List<Invoice>> invoices = this.invoiceClient.getInvoices();
// then
assertNotNull(invoices);
assertEquals(HttpStatus.OK, invoices.getStatusCode());
assertNotNull(invoices.getBody());
assertEquals(100, invoices.getBody().size());
assertThat(invoices).isNotNull();
assertThat(invoices.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(invoices.getBody()).isNotNull();
assertThat(invoices.getBody().size()).isEqualTo(100);
}
@@ -80,6 +78,7 @@ public class FeignAcceptEncodingTests {
@SpringBootApplication(scanBasePackages = "org.springframework.cloud.openfeign.encoding.app")
@Import(NoSecurityConfiguration.class)
public static class Application {
}
@Configuration
@@ -95,5 +94,7 @@ public class FeignAcceptEncodingTests {
Collections.singletonList(new Server("localhost", this.port)));
return balancer;
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -16,23 +16,23 @@
package org.springframework.cloud.openfeign.encoding;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.Collections;
import java.util.List;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.encoding.app.client.InvoiceClient;
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -41,16 +41,15 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* Tests the response compression.
*
* @author Jakub Narloch
*/
@SpringBootTest(classes = FeignContentEncodingTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = {
@SpringBootTest(classes = FeignContentEncodingTests.Application.class, webEnvironment = RANDOM_PORT, value = {
"feign.compression.request.enabled=true",
"hystrix.command.default.execution.isolation.strategy=SEMAPHORE",
"ribbon.OkToRetryOnAllOperations=false" })
@@ -71,10 +70,10 @@ public class FeignContentEncodingTests {
.saveInvoices(invoices);
// then
assertNotNull(response);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
assertEquals(invoices.size(), response.getBody().size());
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().size()).isEqualTo(invoices.size());
}
@@ -83,6 +82,7 @@ public class FeignContentEncodingTests {
@SpringBootApplication(scanBasePackages = "org.springframework.cloud.openfeign.encoding.app")
@Import(NoSecurityConfiguration.class)
public static class Application {
}
@Configuration
@@ -98,5 +98,7 @@ public class FeignContentEncodingTests {
Collections.singletonList(new Server("localhost", this.port)));
return balancer;
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -16,13 +16,13 @@
package org.springframework.cloud.openfeign.encoding;
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
/**
* Utility class used for testing.
*
@@ -35,9 +35,11 @@ final class Invoices {
for (int ind = 0; ind < count; ind++) {
final Invoice invoice = new Invoice();
invoice.setTitle("Invoice " + (ind + 1));
invoice.setAmount(new BigDecimal(String.format(Locale.US, "%.2f", Math.random() * 1000)));
invoice.setAmount(new BigDecimal(
String.format(Locale.US, "%.2f", Math.random() * 1000)));
invoices.add(invoice);
}
return invoices;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -38,4 +38,5 @@ public interface InvoiceClient {
@RequestMapping(value = "invoices", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<List<Invoice>> saveInvoices(List<Invoice> invoices);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -30,7 +30,7 @@ public class Invoice {
private BigDecimal amount;
public String getTitle() {
return title;
return this.title;
}
public void setTitle(String title) {
@@ -38,10 +38,11 @@ public class Invoice {
}
public BigDecimal getAmount() {
return amount;
return this.amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -16,6 +16,11 @@
package org.springframework.cloud.openfeign.encoding.app.resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.springframework.cloud.openfeign.encoding.app.domain.Invoice;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -24,11 +29,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* An sample REST controller, that potentially returns large response - used for testing.
*
@@ -43,8 +43,7 @@ public class InvoiceResource {
return ResponseEntity.ok(createInvoiceList(100));
}
@RequestMapping(value = "invoices", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = "invoices", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<List<Invoice>> saveInvoices(@RequestBody List<Invoice> invoices) {
return ResponseEntity.ok(invoices);
@@ -55,9 +54,11 @@ public class InvoiceResource {
for (int ind = 0; ind < count; ind++) {
final Invoice invoice = new Invoice();
invoice.setTitle("Invoice " + (ind + 1));
invoice.setAmount(new BigDecimal(String.format(Locale.US, "%.2f", Math.random() * 1000)));
invoice.setAmount(new BigDecimal(
String.format(Locale.US, "%.2f", Math.random() * 1000)));
invoices.add(invoice);
}
return invoices;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -39,17 +39,17 @@ import static feign.Request.HttpMethod.POST;
@ClassPathExclusions("protobuf-*.jar")
public class ProtobufNotInClasspathTest {
@Test
public void testEncodeWhenProtobufNotInClasspath() {
ObjectFactory<HttpMessageConverters> converters = new ObjectFactory<HttpMessageConverters>() {
@Override
public HttpMessageConverters getObject() throws BeansException {
return new HttpMessageConverters(new StringHttpMessageConverter());
}
};
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.method(POST);
new SpringEncoder(converters).encode("a=b", String.class, requestTemplate);
}
@Test
public void testEncodeWhenProtobufNotInClasspath() {
ObjectFactory<HttpMessageConverters> converters = new ObjectFactory<HttpMessageConverters>() {
@Override
public HttpMessageConverters getObject() throws BeansException {
return new HttpMessageConverters(new StringHttpMessageConverter());
}
};
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.method(POST);
new SpringEncoder(converters).encode("a=b", String.class, requestTemplate);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -35,7 +35,6 @@ import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
@@ -53,6 +52,8 @@ import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
import static feign.Request.Body.encoded;
import static feign.Request.HttpMethod.POST;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
/**
* Test {@link SpringEncoder} with {@link ProtobufHttpMessageConverter}
@@ -62,87 +63,92 @@ import static feign.Request.HttpMethod.POST;
@RunWith(MockitoJUnitRunner.class)
public class ProtobufSpringEncoderTest {
@Mock
private HttpClient httpClient;
@Mock
private HttpClient httpClient;
// a protobuf object with some content
private org.springframework.cloud.openfeign.encoding.proto.Request request = org.springframework.cloud.openfeign.encoding.proto.Request.newBuilder()
.setId(1000000)
.setMsg("Erlang/OTP 最初是爱立信为开发电信设备系统设计的编程语言平台," +
"电信设备(路由器、接入网关、…)典型设计是通过背板连接主控板卡与多块业务板卡的分布式系统。")
.build();
// a protobuf object with some content
private org.springframework.cloud.openfeign.encoding.proto.Request request = org.springframework.cloud.openfeign.encoding.proto.Request
.newBuilder().setId(1000000).setMsg("Erlang/OTP 最初是爱立信为开发电信设备系统设计的编程语言平台,"
+ "电信设备(路由器、接入网关、…)典型设计是通过背板连接主控板卡与多块业务板卡的分布式系统。")
.build();
@Test
public void testProtobuf() throws IOException, URISyntaxException {
// protobuf convert to request by feign and ProtobufHttpMessageConverter
RequestTemplate requestTemplate = newRequestTemplate();
newEncoder().encode(request, Request.class, requestTemplate);
HttpEntity entity = toApacheHttpEntity(requestTemplate);
byte[] bytes = read(entity.getContent(), (int) entity.getContentLength());
@Test
public void testProtobuf() throws IOException, URISyntaxException {
// protobuf convert to request by feign and ProtobufHttpMessageConverter
RequestTemplate requestTemplate = newRequestTemplate();
newEncoder().encode(this.request, Request.class, requestTemplate);
HttpEntity entity = toApacheHttpEntity(requestTemplate);
byte[] bytes = read(entity.getContent(), (int) entity.getContentLength());
Assert.assertArrayEquals(bytes, request.toByteArray());
org.springframework.cloud.openfeign.encoding.proto.Request copy = org.springframework.cloud.openfeign.encoding.proto.Request.parseFrom(bytes);
Assert.assertEquals(request, copy);
}
assertThat(this.request.toByteArray()).isEqualTo(bytes);
org.springframework.cloud.openfeign.encoding.proto.Request copy = org.springframework.cloud.openfeign.encoding.proto.Request
.parseFrom(bytes);
assertThat(copy).isEqualTo(this.request);
}
@Test
public void testProtobufWithCharsetWillFail() throws IOException, URISyntaxException {
// protobuf convert to request by feign and ProtobufHttpMessageConverter
RequestTemplate requestTemplate = newRequestTemplate();
newEncoder().encode(request, Request.class, requestTemplate);
// set a charset
requestTemplate
.body(encoded(requestTemplate.requestBody()
.asBytes(), StandardCharsets.UTF_8));
HttpEntity entity = toApacheHttpEntity(requestTemplate);
byte[] bytes = read(entity.getContent(), (int) entity.getContentLength());
@Test
public void testProtobufWithCharsetWillFail() throws IOException, URISyntaxException {
// protobuf convert to request by feign and ProtobufHttpMessageConverter
RequestTemplate requestTemplate = newRequestTemplate();
newEncoder().encode(this.request, Request.class, requestTemplate);
// set a charset
requestTemplate.body(
encoded(requestTemplate.requestBody().asBytes(), StandardCharsets.UTF_8));
HttpEntity entity = toApacheHttpEntity(requestTemplate);
byte[] bytes = read(entity.getContent(), (int) entity.getContentLength());
// http request-body is different with original protobuf body
Assert.assertNotEquals(bytes.length, request.toByteArray().length);
try {
org.springframework.cloud.openfeign.encoding.proto.Request copy = org.springframework.cloud.openfeign.encoding.proto.Request.parseFrom(bytes);
Assert.fail("Expected an InvalidProtocolBufferException to be thrown");
} catch (InvalidProtocolBufferException e) {
// success
}
}
// http request-body is different with original protobuf body
assertThat(this.request.toByteArray().length).isNotEqualTo(bytes.length);
try {
org.springframework.cloud.openfeign.encoding.proto.Request copy = org.springframework.cloud.openfeign.encoding.proto.Request
.parseFrom(bytes);
fail("Expected an InvalidProtocolBufferException to be thrown");
}
catch (InvalidProtocolBufferException e) {
// success
}
}
private SpringEncoder newEncoder() {
ObjectFactory<HttpMessageConverters> converters = new ObjectFactory<HttpMessageConverters>() {
@Override
public HttpMessageConverters getObject() throws BeansException {
return new HttpMessageConverters(new ProtobufHttpMessageConverter());
}
};
return new SpringEncoder(converters);
}
private SpringEncoder newEncoder() {
ObjectFactory<HttpMessageConverters> converters = new ObjectFactory<HttpMessageConverters>() {
@Override
public HttpMessageConverters getObject() throws BeansException {
return new HttpMessageConverters(new ProtobufHttpMessageConverter());
}
};
return new SpringEncoder(converters);
}
private RequestTemplate newRequestTemplate() {
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.method(POST);
return requestTemplate;
}
private RequestTemplate newRequestTemplate() {
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.method(POST);
return requestTemplate;
}
private HttpEntity toApacheHttpEntity(RequestTemplate requestTemplate) throws IOException, URISyntaxException {
final List<HttpUriRequest> request = new ArrayList<>(1);
BDDMockito.given(httpClient.execute(ArgumentMatchers.<HttpUriRequest>any()))
.will(new Answer<HttpResponse>() {
@Override
public HttpResponse answer(InvocationOnMock invocationOnMock) throws Throwable {
request.add((HttpUriRequest) invocationOnMock.getArguments()[0]);
return new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion("http", 1, 1), 200, null));
}
});
new ApacheHttpClient(httpClient).execute(requestTemplate.resolve(new HashMap<>())
.request(), new feign.Request.Options());
HttpUriRequest httpUriRequest = request.get(0);
return ((HttpEntityEnclosingRequestBase)httpUriRequest).getEntity();
}
private HttpEntity toApacheHttpEntity(RequestTemplate requestTemplate)
throws IOException, URISyntaxException {
final List<HttpUriRequest> request = new ArrayList<>(1);
BDDMockito.given(this.httpClient.execute(ArgumentMatchers.<HttpUriRequest>any()))
.will(new Answer<HttpResponse>() {
@Override
public HttpResponse answer(InvocationOnMock invocationOnMock)
throws Throwable {
request.add((HttpUriRequest) invocationOnMock.getArguments()[0]);
return new BasicHttpResponse(new BasicStatusLine(
new ProtocolVersion("http", 1, 1), 200, null));
}
});
new ApacheHttpClient(this.httpClient).execute(
requestTemplate.resolve(new HashMap<>()).request(),
new feign.Request.Options());
HttpUriRequest httpUriRequest = request.get(0);
return ((HttpEntityEnclosingRequestBase) httpUriRequest).getEntity();
}
private byte[] read(InputStream in, int length) throws IOException {
byte[] bytes = new byte[length];
in.read(bytes);
return bytes;
}
private byte[] read(InputStream in, int length) throws IOException {
byte[] bytes = new byte[length];
in.read(bytes);
return bytes;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2013-2019 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.
@@ -20,53 +20,48 @@
package org.springframework.cloud.openfeign.encoding.proto;
public final class ProtobufTest {
private ProtobufTest() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
static final com.google.protobuf.Descriptors.Descriptor
internal_static_Request_descriptor;
static final
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_Request_fieldAccessorTable;
static final com.google.protobuf.Descriptors.Descriptor internal_static_Request_descriptor;
static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_Request_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
String[] descriptorData = {
"\n\023protobuf_test.proto\"\"\n\007Request\022\n\n\002id\030\001" +
" \001(\005\022\013\n\003msg\030\002 \001(\tB\024\n\020feign.httpclientP\001b" +
"\006proto3"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
}, assigner);
internal_static_Request_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_Request_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_Request_descriptor,
new String[] { "Id", "Msg", });
}
private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
static {
String[] descriptorData = {
"\n\023protobuf_test.proto\"\"\n\007Request\022\n\n\002id\030\001"
+ " \001(\005\022\013\n\003msg\030\002 \001(\tB\024\n\020feign.httpclientP\001b"
+ "\006proto3" };
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(
descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {},
assigner);
internal_static_Request_descriptor = getDescriptor().getMessageTypes().get(0);
internal_static_Request_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_Request_descriptor, new String[] { "Id", "Msg", });
}
private ProtobufTest() {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry);
}
public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
return descriptor;
}
// @@protoc_insertion_point(outer_class_scope)
// @@protoc_insertion_point(outer_class_scope)
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2013-2019 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.
@@ -20,21 +20,22 @@
package org.springframework.cloud.openfeign.encoding.proto;
public interface RequestOrBuilder extends
// @@protoc_insertion_point(interface_extends:Request)
com.google.protobuf.MessageOrBuilder {
// @@protoc_insertion_point(interface_extends:Request)
com.google.protobuf.MessageOrBuilder {
/**
* <code>int32 id = 1;</code>
*/
int getId();
/**
* <code>int32 id = 1;</code>
*/
int getId();
/**
* <code>string msg = 2;</code>
*/
String getMsg();
/**
* <code>string msg = 2;</code>
*/
com.google.protobuf.ByteString getMsgBytes();
/**
* <code>string msg = 2;</code>
*/
String getMsg();
/**
* <code>string msg = 2;</code>
*/
com.google.protobuf.ByteString
getMsgBytes();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -51,50 +51,27 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests that a secured web service returning values using a feign client properly access
* the security context from a hystrix command.
*
* @author Daniel Lavoie
*/
@RunWith(SpringRunner.class)
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT,
properties = { "feign.hystrix.enabled=true"})
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
"feign.hystrix.enabled=true" })
@ActiveProfiles("proxysecurity")
public class HystrixSecurityTests {
@Autowired
private CustomConcurrenyStrategy customConcurrenyStrategy;
@LocalServerPort
private String serverPort;
//TODO: move to constants in TestAutoConfiguration
// TODO: move to constants in TestAutoConfiguration
private String username = "user";
private String password = "password";
@Test
public void testSecurityConcurrencyStrategyInstalled() {
HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
assertThat(concurrencyStrategy).isInstanceOf(SecurityContextConcurrencyStrategy.class);
}
@Test
public void testFeignHystrixSecurity() {
HttpHeaders headers = createBasicAuthHeader(username, password);
ResponseEntity<String> entity = new RestTemplate()
.exchange("http://localhost:" + serverPort + "/proxy-username",
HttpMethod.GET, new HttpEntity<Void>(headers), String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody())
.as("Username should have been intercepted by feign interceptor.")
.isEqualTo(username);
assertThat(customConcurrenyStrategy.isHookCalled())
.as("Custom hook should have been called.")
.isTrue();
}
public static HttpHeaders createBasicAuthHeader(final String username,
final String password) {
return new HttpHeaders() {
@@ -109,10 +86,38 @@ public class HystrixSecurityTests {
};
}
@Test
public void testSecurityConcurrencyStrategyInstalled() {
HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance()
.getConcurrencyStrategy();
assertThat(concurrencyStrategy)
.isInstanceOf(SecurityContextConcurrencyStrategy.class);
}
@Test
public void testFeignHystrixSecurity() {
HttpHeaders headers = createBasicAuthHeader(this.username, this.password);
ResponseEntity<String> entity = new RestTemplate().exchange(
"http://localhost:" + this.serverPort + "/proxy-username", HttpMethod.GET,
new HttpEntity<Void>(headers), String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody())
.as("Username should have been intercepted by feign interceptor.")
.isEqualTo(this.username);
assertThat(this.customConcurrenyStrategy.isHookCalled())
.as("Custom hook should have been called.").isTrue();
}
@SpringBootConfiguration
@Import(HystrixSecurityApplication.class)
@RibbonClient(name = "username", configuration = LocalRibbonClientConfiguration.class)
protected static class TestConfig { }
protected static class TestConfig {
}
protected static class LocalRibbonClientConfiguration {
@@ -125,4 +130,5 @@ public class HystrixSecurityTests {
}
}
}

View File

@@ -1,10 +1,27 @@
package org.springframework.cloud.openfeign.hystrix.security.app;
/*
* Copyright 2013-2019 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.
*/
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
package org.springframework.cloud.openfeign.hystrix.security.app;
import java.util.concurrent.Callable;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
public class CustomConcurrenyStrategy extends HystrixConcurrencyStrategy {
private boolean hookCalled;
@Override
@@ -15,6 +32,7 @@ public class CustomConcurrenyStrategy extends HystrixConcurrencyStrategy {
}
public boolean isHookCalled() {
return hookCalled;
return this.hookCalled;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 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.
@@ -26,11 +26,13 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/proxy-username")
public class ProxyUsernameController {
@Autowired
private UsernameClient usernameClient;
@RequestMapping
public String getUsername() {
return usernameClient.getUsername();
return this.usernameClient.getUsername();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -24,15 +24,17 @@ import org.springframework.security.core.context.SecurityContextHolder;
/**
* This interceptor should be called from an Hyxtrix command execution thread. It is
* access the SecurityContext and settings an http header from the authentication details.
*
*
* @author Daniel Lavoie
*/
public class TestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
if (SecurityContextHolder.getContext().getAuthentication() != null)
if (SecurityContextHolder.getContext().getAuthentication() != null) {
template.header("username",
SecurityContextHolder.getContext().getAuthentication().getName());
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 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.
@@ -27,4 +27,5 @@ public interface UsernameClient {
@RequestMapping("/username")
String getUsername();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2016 the original author or authors.
* Copyright 2013-2019 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.
@@ -26,8 +26,10 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/username")
public class UsernameController {
@RequestMapping
public String getUsername(@RequestHeader String username){
public String getUsername(@RequestHeader String username) {
return username;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -19,10 +19,10 @@ package org.springframework.cloud.openfeign.invalid;
import feign.Feign;
import feign.hystrix.FallbackFactory;
import feign.hystrix.HystrixFeign;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
@@ -37,7 +37,7 @@ import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import static org.junit.Assert.assertNotNull;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Dave Syer
@@ -53,6 +53,81 @@ public class FeignClientValidationTests {
new AnnotationConfigApplicationContext(NameAndValueConfiguration.class);
}
@Test
public void testServiceIdAndValue() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
LoadBalancerAutoConfiguration.class, RibbonAutoConfiguration.class,
FeignRibbonClientAutoConfiguration.class,
NameAndServiceIdConfiguration.class);
assertThat(context.getBean(NameAndServiceIdConfiguration.Client.class))
.isNotNull();
context.close();
}
@Test
public void testDuplicatedClientNames() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.setAllowBeanDefinitionOverriding(false);
context.register(LoadBalancerAutoConfiguration.class,
RibbonAutoConfiguration.class, FeignRibbonClientAutoConfiguration.class,
DuplicatedFeignClientNamesConfiguration.class);
context.refresh();
assertThat(
context.getBean(DuplicatedFeignClientNamesConfiguration.FooClient.class))
.isNotNull();
assertThat(
context.getBean(DuplicatedFeignClientNamesConfiguration.BarClient.class))
.isNotNull();
context.close();
}
@Test
public void testNotLegalHostname() {
this.expected.expectMessage("not legal hostname (foo_bar)");
new AnnotationConfigApplicationContext(BadHostnameConfiguration.class);
}
@Test
public void testMissingFallback() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MissingFallbackConfiguration.class)) {
this.expected.expectMessage("No fallback instance of type");
assertThat(context.getBean(MissingFallbackConfiguration.Client.class))
.isNotNull();
}
}
@Test
public void testWrongFallbackType() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
WrongFallbackTypeConfiguration.class)) {
this.expected.expectMessage("Incompatible fallback instance");
assertThat(context.getBean(WrongFallbackTypeConfiguration.Client.class))
.isNotNull();
}
}
@Test
public void testMissingFallbackFactory() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MissingFallbackFactoryConfiguration.class)) {
this.expected.expectMessage("No fallbackFactory instance of type");
assertThat(context.getBean(MissingFallbackFactoryConfiguration.Client.class))
.isNotNull();
}
}
@Test
public void testWrongFallbackFactoryType() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
WrongFallbackFactoryTypeConfiguration.class)) {
this.expected.expectMessage("Incompatible fallbackFactory instance");
assertThat(
context.getBean(WrongFallbackFactoryTypeConfiguration.Client.class))
.isNotNull();
}
}
@Configuration
@Import(FeignAutoConfiguration.class)
@EnableFeignClients(clients = NameAndValueConfiguration.Client.class)
@@ -60,75 +135,53 @@ public class FeignClientValidationTests {
@FeignClient(value = "foo", name = "bar")
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
}
@Test
public void testServiceIdAndValue() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
LoadBalancerAutoConfiguration.class,
RibbonAutoConfiguration.class,
FeignRibbonClientAutoConfiguration.class,
NameAndServiceIdConfiguration.class);
assertNotNull(context.getBean(NameAndServiceIdConfiguration.Client.class));
context.close();
}
@Configuration
@Import({FeignAutoConfiguration.class, HttpClientConfiguration.class})
@Import({ FeignAutoConfiguration.class, HttpClientConfiguration.class })
@EnableFeignClients(clients = NameAndServiceIdConfiguration.Client.class)
protected static class NameAndServiceIdConfiguration {
@FeignClient(name = "bar", serviceId = "foo")
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
}
@Test
public void testDuplicatedClientNames() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.setAllowBeanDefinitionOverriding(false);
context.register(
LoadBalancerAutoConfiguration.class,
RibbonAutoConfiguration.class,
FeignRibbonClientAutoConfiguration.class,
DuplicatedFeignClientNamesConfiguration.class
);
context.refresh();
assertNotNull(context.getBean(DuplicatedFeignClientNamesConfiguration.FooClient.class));
assertNotNull(context.getBean(DuplicatedFeignClientNamesConfiguration.BarClient.class));
context.close();
}
}
@Configuration
@Import({FeignAutoConfiguration.class, HttpClientConfiguration.class})
@EnableFeignClients(clients = {DuplicatedFeignClientNamesConfiguration.FooClient.class,
DuplicatedFeignClientNamesConfiguration.BarClient.class})
@Import({ FeignAutoConfiguration.class, HttpClientConfiguration.class })
@EnableFeignClients(clients = {
DuplicatedFeignClientNamesConfiguration.FooClient.class,
DuplicatedFeignClientNamesConfiguration.BarClient.class })
protected static class DuplicatedFeignClientNamesConfiguration {
@FeignClient(contextId = "foo", name = "bar")
interface FooClient {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
@FeignClient(name = "bar")
interface BarClient {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
}
@Test
public void testNotLegalHostname() {
this.expected.expectMessage("not legal hostname (foo_bar)");
new AnnotationConfigApplicationContext(BadHostnameConfiguration.class);
}
}
@Configuration
@@ -138,53 +191,41 @@ public class FeignClientValidationTests {
@FeignClient("foo_bar")
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
}
@Test
public void testMissingFallback() {
try (
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MissingFallbackConfiguration.class)) {
this.expected.expectMessage("No fallback instance of type");
assertNotNull(context.getBean(MissingFallbackConfiguration.Client.class));
}
}
@Configuration
@Import(FeignAutoConfiguration.class)
@EnableFeignClients(clients = MissingFallbackConfiguration.Client.class)
protected static class MissingFallbackConfiguration {
@FeignClient(name = "foobar", url = "http://localhost", fallback = ClientFallback.class)
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
class ClientFallback implements Client {
@Override
public String get() {
return null;
}
}
@Bean
public Feign.Builder feignBuilder() {
return HystrixFeign.builder();
}
}
@Test
public void testWrongFallbackType() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
WrongFallbackTypeConfiguration.class)) {
this.expected.expectMessage("Incompatible fallback instance");
assertNotNull(context.getBean(WrongFallbackTypeConfiguration.Client.class));
@FeignClient(name = "foobar", url = "http://localhost", fallback = ClientFallback.class)
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
class ClientFallback implements Client {
@Override
public String get() {
return null;
}
}
}
@Configuration
@@ -192,34 +233,28 @@ public class FeignClientValidationTests {
@EnableFeignClients(clients = WrongFallbackTypeConfiguration.Client.class)
protected static class WrongFallbackTypeConfiguration {
@FeignClient(name = "foobar", url = "http://localhost", fallback = Dummy.class)
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
@Bean
Dummy dummy() {
return new Dummy();
}
class Dummy {
}
@Bean
public Feign.Builder feignBuilder() {
return HystrixFeign.builder();
}
}
@FeignClient(name = "foobar", url = "http://localhost", fallback = Dummy.class)
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
@Test
public void testMissingFallbackFactory() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MissingFallbackFactoryConfiguration.class)) {
this.expected.expectMessage("No fallbackFactory instance of type");
assertNotNull(context.getBean(MissingFallbackFactoryConfiguration.Client.class));
}
class Dummy {
}
}
@Configuration
@@ -227,10 +262,17 @@ public class FeignClientValidationTests {
@EnableFeignClients(clients = MissingFallbackFactoryConfiguration.Client.class)
protected static class MissingFallbackFactoryConfiguration {
@Bean
public Feign.Builder feignBuilder() {
return HystrixFeign.builder();
}
@FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = ClientFallback.class)
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
class ClientFallback implements FallbackFactory<Client> {
@@ -239,21 +281,9 @@ public class FeignClientValidationTests {
public Client create(Throwable cause) {
return null;
}
}
@Bean
public Feign.Builder feignBuilder() {
return HystrixFeign.builder();
}
}
@Test
public void testWrongFallbackFactoryType() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
WrongFallbackFactoryTypeConfiguration.class)) {
this.expected.expectMessage("Incompatible fallbackFactory instance");
assertNotNull(context.getBean(WrongFallbackFactoryTypeConfiguration.Client.class));
}
}
@Configuration
@@ -261,24 +291,28 @@ public class FeignClientValidationTests {
@EnableFeignClients(clients = WrongFallbackFactoryTypeConfiguration.Client.class)
protected static class WrongFallbackFactoryTypeConfiguration {
@FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = Dummy.class)
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
@Bean
Dummy dummy() {
return new Dummy();
}
class Dummy {
}
@Bean
public Feign.Builder feignBuilder() {
return HystrixFeign.builder();
}
@FeignClient(name = "foobar", url = "http://localhost", fallbackFactory = Dummy.class)
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
String get();
}
class Dummy {
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -23,10 +23,11 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryFactory;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import static org.junit.Assert.assertNotNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -56,13 +57,13 @@ public class CachingSpringLoadBalancerFactoryTests {
when(this.delegate.getClientConfig("client2")).thenReturn(config);
this.factory = new CachingSpringLoadBalancerFactory(this.delegate,
loadBalancedRetryFactory);
this.loadBalancedRetryFactory);
}
@Test
public void delegateCreatesWhenMissing() {
FeignLoadBalancer client = this.factory.create("client1");
assertNotNull("client was null", client);
assertThat(client).as("client was null").isNotNull();
verify(this.delegate, times(1)).getClientConfig("client1");
}
@@ -70,10 +71,10 @@ public class CachingSpringLoadBalancerFactoryTests {
@Test
public void cacheWorks() {
FeignLoadBalancer client = this.factory.create("client2");
assertNotNull("client was null", client);
assertThat(client).as("client was null").isNotNull();
client = this.factory.create("client2");
assertNotNull("client was null", client);
assertThat(client).as("client was null").isNotNull();
verify(this.delegate, times(1)).getClientConfig("client2");
}
@@ -84,9 +85,10 @@ public class CachingSpringLoadBalancerFactoryTests {
config.set(CommonClientConfigKey.ConnectTimeout, 1000);
config.set(CommonClientConfigKey.ReadTimeout, 500);
when(this.delegate.getClientConfig("retry")).thenReturn(config);
CachingSpringLoadBalancerFactory factory = new CachingSpringLoadBalancerFactory(this.delegate);
CachingSpringLoadBalancerFactory factory = new CachingSpringLoadBalancerFactory(
this.delegate);
FeignLoadBalancer client = this.factory.create("retry");
assertNotNull("client was null", client);
assertThat(client).as("client was null").isNotNull();
}
@Test
@@ -95,8 +97,10 @@ public class CachingSpringLoadBalancerFactoryTests {
config.set(CommonClientConfigKey.ConnectTimeout, 1000);
config.set(CommonClientConfigKey.ReadTimeout, 500);
when(this.delegate.getClientConfig("retry")).thenReturn(config);
CachingSpringLoadBalancerFactory factory = new CachingSpringLoadBalancerFactory(this.delegate, loadBalancedRetryFactory);
CachingSpringLoadBalancerFactory factory = new CachingSpringLoadBalancerFactory(
this.delegate, this.loadBalancedRetryFactory);
FeignLoadBalancer client = this.factory.create("retry");
assertNotNull("client was null", client);
assertThat(client).as("client was null").isNotNull();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,7 +12,6 @@
* 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.cloud.openfeign.ribbon;
@@ -53,8 +52,7 @@ import static com.netflix.client.config.CommonClientConfigKey.ReadTimeout;
import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_MAX_AUTO_RETRIES;
import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_MAX_AUTO_RETRIES_NEXT_SERVER;
import static feign.Request.HttpMethod.GET;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
@@ -64,8 +62,10 @@ public class FeignLoadBalancerTests {
@Mock
private Client delegate;
@Mock
private ILoadBalancer lb;
@Mock
private IClientConfig config;
@@ -74,6 +74,7 @@ public class FeignLoadBalancerTests {
private ServerIntrospector inspector = new DefaultServerIntrospector();
private Integer defaultConnectTimeout = 10000;
private Integer defaultReadTimeout = 10000;
@Before
@@ -95,27 +96,19 @@ public class FeignLoadBalancerTests {
this.feignLoadBalancer = new FeignLoadBalancer(this.lb, this.config,
this.inspector);
Request request = new RequestTemplate()
.method(GET)
.target("http://foo/")
.resolve(new HashMap<>())
.request();
Request request = new RequestTemplate().method(GET).target("http://foo/")
.resolve(new HashMap<>()).request();
RibbonRequest ribbonRequest = new RibbonRequest(this.delegate, request,
new URI(request.url()));
Response response = Response.builder()
.request(request)
.status(200)
.reason("Test")
.headers(Collections.emptyMap())
.body(new byte[0])
.build();
Response response = Response.builder().request(request).status(200).reason("Test")
.headers(Collections.emptyMap()).body(new byte[0]).build();
when(this.delegate.execute(any(Request.class), any(Options.class)))
.thenReturn(response);
RibbonResponse resp = this.feignLoadBalancer.execute(ribbonRequest, null);
assertThat(resp.getRequestedURI(), is(new URI("http://foo")));
assertThat(resp.getRequestedURI()).isEqualTo(new URI("http://foo"));
}
@Test
@@ -126,7 +119,7 @@ public class FeignLoadBalancerTests {
Server server = new Server("foo", 7777);
URI uri = this.feignLoadBalancer.reconstructURIWithServer(server,
new URI("http://foo/"));
assertThat(uri, is(new URI("https://foo:7777/")));
assertThat(uri).isEqualTo(new URI("https://foo:7777/"));
}
@Test
@@ -148,7 +141,7 @@ public class FeignLoadBalancerTests {
Server server = new Server("foo", 7777);
URI uri = this.feignLoadBalancer.reconstructURIWithServer(server,
new URI("http://foo/"));
assertThat(uri, is(new URI("http://foo:7777/")));
assertThat(uri).isEqualTo(new URI("http://foo:7777/"));
}
@Test
@@ -160,21 +153,22 @@ public class FeignLoadBalancerTests {
when(server.getHost()).thenReturn("foo");
URI uri = this.feignLoadBalancer.reconstructURIWithServer(server,
new URI("http://bar/"));
assertThat(uri, is(new URI("https://foo:443/")));
assertThat(uri).isEqualTo(new URI("https://foo:443/"));
}
@Test
public void testRibbonRequestURLEncode() throws Exception {
String url = "http://foo/?name=%7bcookie";//name={cookie
String url = "http://foo/?name=%7bcookie"; // name={cookie
Request request = Request.create(GET, url, new HashMap<>(), null, null);
assertThat(request.url(),is(url));
assertThat(request.url()).isEqualTo(url);
RibbonRequest ribbonRequest = new RibbonRequest(this.delegate,request,new URI(request.url()));
RibbonRequest ribbonRequest = new RibbonRequest(this.delegate, request,
new URI(request.url()));
Request cloneRequest = ribbonRequest.toRequest();
assertThat(cloneRequest.url(),is(url));
assertThat(cloneRequest.url()).isEqualTo(url);
}
@@ -193,23 +187,23 @@ public class FeignLoadBalancerTests {
this.feignLoadBalancer = new FeignLoadBalancer(baseLoadBalancer, this.config,
this.inspector) {
protected void customizeLoadBalancerCommandBuilder(final FeignLoadBalancer.RibbonRequest request, final IClientConfig config,
final LoadBalancerCommand.Builder<FeignLoadBalancer.RibbonResponse> builder) {
protected void customizeLoadBalancerCommandBuilder(
final FeignLoadBalancer.RibbonRequest request,
final IClientConfig config,
final LoadBalancerCommand.Builder<FeignLoadBalancer.RibbonResponse> builder) {
builder.withServerLocator(request.getRequest().headers().get("c_ip"));
}
};
Request request = new RequestTemplate().method(GET).resolve(new HashMap<>()).request();
RibbonResponse resp = this.feignLoadBalancer.executeWithLoadBalancer(new RibbonRequest(this.delegate, request,
new URI(request.url())), null);
assertThat(resp.getRequestedURI().getPort(), is(7777));
request = new RequestTemplate()
.method(GET)
.header("c_ip", "666")
.resolve(new HashMap<>())
Request request = new RequestTemplate().method(GET).resolve(new HashMap<>())
.request();
resp = this.feignLoadBalancer.executeWithLoadBalancer(new RibbonRequest(this.delegate, request,
new URI(request.url())), null);
assertThat(resp.getRequestedURI().getPort(), is(6666));
RibbonResponse resp = this.feignLoadBalancer.executeWithLoadBalancer(
new RibbonRequest(this.delegate, request, new URI(request.url())), null);
assertThat(resp.getRequestedURI().getPort()).isEqualTo(7777);
request = new RequestTemplate().method(GET).header("c_ip", "666")
.resolve(new HashMap<>()).request();
resp = this.feignLoadBalancer.executeWithLoadBalancer(
new RibbonRequest(this.delegate, request, new URI(request.url())), null);
assertThat(resp.getRequestedURI().getPort()).isEqualTo(6666);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -25,7 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.openfeign.EnableFeignClients;
@@ -40,21 +39,18 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Venil Noronha
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = FeignRibbonClientPathTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT,value = {
"spring.application.name=feignribbonclientpathtest",
"feign.okhttp.enabled=false",
"feign.httpclient.enabled=false",
"feign.hystrix.enabled=false",
@SpringBootTest(classes = FeignRibbonClientPathTests.Application.class, webEnvironment = RANDOM_PORT, value = {
"spring.application.name=feignribbonclientpathtest", "feign.okhttp.enabled=false",
"feign.httpclient.enabled=false", "feign.hystrix.enabled=false",
"test.path.prefix=/base/path" // For pathWithPlaceholder test
}
)
})
@DirtiesContext
public class FeignRibbonClientPathTests {
@@ -72,51 +68,10 @@ public class FeignRibbonClientPathTests {
@Autowired
private TestClient4 testClient4;
@Autowired
private TestClient5 testClient5;
protected interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello getHello();
}
@FeignClient(name = "localapp", path = "/base/path")
protected interface TestClient1 extends TestClient { }
@FeignClient(name = "localapp1", path = "base/path")
protected interface TestClient2 extends TestClient { }
@FeignClient(name = "localapp2", path = "base/path/")
protected interface TestClient3 extends TestClient { }
@FeignClient(name = "localapp3", path = "/base/path/")
protected interface TestClient4 extends TestClient { }
@FeignClient(name = "localapp4", path = "${test.path.prefix}")
protected interface TestClient5 extends TestClient { }
@Configuration
@EnableAutoConfiguration
@RestController
@RequestMapping("/base/path")
@EnableFeignClients(clients = {
TestClient1.class, TestClient2.class, TestClient3.class, TestClient4.class,
TestClient5.class
})
@RibbonClients(defaultConfiguration = LocalRibbonClientConfiguration.class)
@Import(NoSecurityConfiguration.class)
public static class Application {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello() {
return new Hello("hello world");
}
}
@Test
public void pathWithLeadingButNotTrailingSlash() {
testClientPath(this.testClient1);
@@ -144,27 +99,79 @@ public class FeignRibbonClientPathTests {
private void testClientPath(TestClient testClient) {
Hello hello = testClient.getHello();
assertNotNull("Object returned was null", hello);
assertEquals("Response object value didn't match", "hello world",
hello.getMessage());
assertThat(hello).as("Object returned was null").isNotNull();
assertThat(hello.getMessage()).as("Response object value didn't match")
.isEqualTo("hello world");
}
protected interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello getHello();
}
@FeignClient(name = "localapp", path = "/base/path")
protected interface TestClient1 extends TestClient {
}
@FeignClient(name = "localapp1", path = "base/path")
protected interface TestClient2 extends TestClient {
}
@FeignClient(name = "localapp2", path = "base/path/")
protected interface TestClient3 extends TestClient {
}
@FeignClient(name = "localapp3", path = "/base/path/")
protected interface TestClient4 extends TestClient {
}
@FeignClient(name = "localapp4", path = "${test.path.prefix}")
protected interface TestClient5 extends TestClient {
}
@Configuration
@EnableAutoConfiguration
@RestController
@RequestMapping("/base/path")
@EnableFeignClients(clients = { TestClient1.class, TestClient2.class,
TestClient3.class, TestClient4.class, TestClient5.class })
@RibbonClients(defaultConfiguration = LocalRibbonClientConfiguration.class)
@Import(NoSecurityConfiguration.class)
public static class Application {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello() {
return new Hello("hello world");
}
}
public static class Hello {
private String message;
public Hello() {}
public Hello() {
}
public Hello(String message) {
this.message = message;
}
public String getMessage() {
return message;
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -20,17 +20,19 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.concurrent.atomic.AtomicInteger;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -41,22 +43,20 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* Tests the Feign Retryer, not ribbon retry.
*
* @author Spencer Gibb
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = FeignRibbonClientRetryTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = {
@SpringBootTest(classes = FeignRibbonClientRetryTests.Application.class, webEnvironment = RANDOM_PORT, value = {
"spring.application.name=feignclientretrytest", "feign.okhttp.enabled=false",
"feign.httpclient.enabled=false", "feign.hystrix.enabled=false", "localapp.ribbon.MaxAutoRetries=2",
"localapp.ribbon.MaxAutoRetriesNextServer=3"})
"feign.httpclient.enabled=false", "feign.hystrix.enabled=false",
"localapp.ribbon.MaxAutoRetries=2",
"localapp.ribbon.MaxAutoRetriesNextServer=3" })
@DirtiesContext
public class FeignRibbonClientRetryTests {
@@ -66,13 +66,32 @@ public class FeignRibbonClientRetryTests {
@Autowired
private TestClient testClient;
@Test
public void testClient() {
assertThat(this.testClient).as("testClient was null").isNotNull();
assertThat(Proxy.isProxyClass(this.testClient.getClass()))
.as("testClient is not a java Proxy").isTrue();
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.testClient);
assertThat(invocationHandler).as("invocationHandler was null").isNotNull();
}
@Test
public void testRetries() {
int retryMe = this.testClient.retryMe();
assertThat(1).as("retryCount didn't match").isEqualTo(retryMe);
// TODO: not sure how to verify retry happens. Debugging through it, it works
// maybe the assertEquals above is enough because of the bogus servers
}
@FeignClient("localapp")
protected interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello getHello();
@RequestMapping(method = RequestMethod.GET, value = "/retryme")
int retryMe();
}
@Configuration
@@ -94,27 +113,11 @@ public class FeignRibbonClientRetryTests {
public int retryMe() {
return this.retries.getAndIncrement();
}
}
@Test
public void testClient() {
assertNotNull("testClient was null", this.testClient);
assertTrue("testClient is not a java Proxy",
Proxy.isProxyClass(this.testClient.getClass()));
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.testClient);
assertNotNull("invocationHandler was null", invocationHandler);
}
@Test
public void testRetries() {
int retryMe = this.testClient.retryMe();
assertEquals("retryCount didn't match", retryMe, 1);
// TODO: not sure how to verify retry happens. Debugging through it, it works
// maybe the assertEquals above is enough because of the bogus servers
}
public static class Hello {
private String message;
public Hello() {
@@ -125,13 +128,15 @@ public class FeignRibbonClientRetryTests {
}
public String getMessage() {
return message;
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
}
}
// Load balancer with fixed server list for "local" pointing to localhost
@@ -145,8 +150,8 @@ class LocalRibbonClientConfiguration {
@Bean
public ServerList<Server> ribbonServerList() {
return new StaticServerList<>(new Server("mybadhost", 80),
new Server("mybadhost2", 10002),
new Server("mybadhost3", 10003), new Server("localhost", this.port));
new Server("mybadhost2", 10002), new Server("mybadhost3", 10003),
new Server("localhost", this.port));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -52,6 +52,7 @@ import static org.mockito.hamcrest.MockitoHamcrest.argThat;
public class FeignRibbonClientTests {
private AbstractLoadBalancer loadBalancer = mock(AbstractLoadBalancer.class);
private Client delegate = mock(Client.class);
private SpringClientFactory factory = new SpringClientFactory() {
@@ -81,71 +82,58 @@ public class FeignRibbonClientTests {
// Even though we don't maintain FeignRibbonClient, keep these tests
// around to make sure the expected behaviour doesn't break
private Client client = new LoadBalancerFeignClient(this.delegate, new CachingSpringLoadBalancerFactory(this.factory), this.factory);
private Client client = new LoadBalancerFeignClient(this.delegate,
new CachingSpringLoadBalancerFactory(this.factory), this.factory);
@Before
public void init() {
when(this.loadBalancer.chooseServer(any())).thenReturn(
new Server("foo.com", 8000));
//to fix NPE
when(this.loadBalancer.chooseServer(any()))
.thenReturn(new Server("foo.com", 8000));
// to fix NPE
LoadBalancerStats stats = mock(LoadBalancerStats.class);
when(this.loadBalancer.getLoadBalancerStats()).thenReturn(stats);
when(stats.getSingleServerStat(any(Server.class))).thenReturn(mock(ServerStats.class));
when(stats.getSingleServerStat(any(Server.class)))
.thenReturn(mock(ServerStats.class));
}
@Test
public void remoteRequestIsSentAtRoot() throws Exception {
Request request = new RequestTemplate()
.method(GET)
.target("http://foo")
.resolve(new HashMap<>())
.request();
Request request = new RequestTemplate().method(GET).target("http://foo")
.resolve(new HashMap<>()).request();
this.client.execute(request, new Options());
RequestMatcher matcher = new RequestMatcher("http://foo.com:8000/");
verify(this.delegate).execute(argThat(matcher),
any(Options.class));
verify(this.delegate).execute(argThat(matcher), any(Options.class));
}
@Test
public void remoteRequestIsSent() throws Exception {
Request request = new RequestTemplate()
.method(GET)
.target("http://foo/")
.resolve(new HashMap<>())
.request();
Request request = new RequestTemplate().method(GET).target("http://foo/")
.resolve(new HashMap<>()).request();
this.client.execute(request, new Options());
RequestMatcher matcher = new RequestMatcher("http://foo.com:8000/");
verify(this.delegate).execute(argThat(matcher),
any(Options.class));
verify(this.delegate).execute(argThat(matcher), any(Options.class));
}
@Test
public void verifyCleanUrl() throws Exception {
Request request = new RequestTemplate()
.method(GET)
.target("http://tp/abc/bcd.json")
.resolve(new HashMap<>())
.request();
Request request = new RequestTemplate().method(GET)
.target("http://tp/abc/bcd.json").resolve(new HashMap<>()).request();
this.client.execute(request, new Options());
RequestMatcher matcher = new RequestMatcher("http://foo.com:8000/abc/bcd.json");
verify(this.delegate).execute(argThat(matcher),
any(Options.class));
verify(this.delegate).execute(argThat(matcher), any(Options.class));
}
@Test
public void remoteRequestIsSecure() throws Exception {
Request request = new RequestTemplate()
.method(GET)
.target("https://foo/")
.resolve(new HashMap<>())
.request();
Request request = new RequestTemplate().method(GET).target("https://foo/")
.resolve(new HashMap<>()).request();
this.client.execute(request, new Options());
RequestMatcher matcher = new RequestMatcher("https://foo.com:8000/");
verify(this.delegate).execute(argThat(matcher),
any(Options.class));
verify(this.delegate).execute(argThat(matcher), any(Options.class));
}
private final static class RequestMatcher extends CustomMatcher<Request> {
private String url;
private RequestMatcher(String url) {
@@ -158,6 +146,7 @@ public class FeignRibbonClientTests {
Request request = (Request) item;
return request.url().equals(this.url);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,40 +12,40 @@
* 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.cloud.openfeign.ribbon;
import java.lang.reflect.Field;
import javax.net.ssl.SSLContextSpi;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
import org.apache.http.config.Lookup;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.impl.conn.DefaultHttpClientConnectionOperator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientRetryTests;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.ReflectionUtils;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Ryan Baxter
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = FeignRibbonHttpClientConfigurationTests.FeignRibbonHttpClientConfigurationTestsApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"debug=true","feign.httpclient.disableSslValidation=true"})
@SpringBootTest(classes = FeignRibbonHttpClientConfigurationTests.FeignRibbonHttpClientConfigurationTestsApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"debug=true", "feign.httpclient.disableSslValidation=true" })
@DirtiesContext
public class FeignRibbonHttpClientConfigurationTests {
@@ -54,21 +54,29 @@ public class FeignRibbonHttpClientConfigurationTests {
@Test
public void disableSslTest() throws Exception {
Lookup<ConnectionSocketFactory> socketFactoryRegistry = getConnectionSocketFactoryLookup(connectionManager);
assertNotNull(socketFactoryRegistry.lookup("https"));
assertNull(this.getX509TrustManager(socketFactoryRegistry).getAcceptedIssuers());
Lookup<ConnectionSocketFactory> socketFactoryRegistry = getConnectionSocketFactoryLookup(
this.connectionManager);
assertThat(socketFactoryRegistry.lookup("https")).isNotNull();
assertThat(this.getX509TrustManager(socketFactoryRegistry).getAcceptedIssuers())
.isNull();
}
private Lookup<ConnectionSocketFactory> getConnectionSocketFactoryLookup(HttpClientConnectionManager connectionManager) {
DefaultHttpClientConnectionOperator connectionOperator = (DefaultHttpClientConnectionOperator)this.getField(connectionManager, "connectionOperator");
return (Lookup)this.getField(connectionOperator, "socketFactoryRegistry");
private Lookup<ConnectionSocketFactory> getConnectionSocketFactoryLookup(
HttpClientConnectionManager connectionManager) {
DefaultHttpClientConnectionOperator connectionOperator = (DefaultHttpClientConnectionOperator) this
.getField(connectionManager, "connectionOperator");
return (Lookup) this.getField(connectionOperator, "socketFactoryRegistry");
}
private X509TrustManager getX509TrustManager(Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
ConnectionSocketFactory connectionSocketFactory = (ConnectionSocketFactory)socketFactoryRegistry.lookup("https");
SSLSocketFactory sslSocketFactory = (SSLSocketFactory)this.getField(connectionSocketFactory, "socketfactory");
SSLContextSpi sslContext = (SSLContextSpi)this.getField(sslSocketFactory, "context");
return (X509TrustManager)this.getField(sslContext, "trustManager");
private X509TrustManager getX509TrustManager(
Lookup<ConnectionSocketFactory> socketFactoryRegistry) {
ConnectionSocketFactory connectionSocketFactory = (ConnectionSocketFactory) socketFactoryRegistry
.lookup("https");
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) this
.getField(connectionSocketFactory, "socketfactory");
SSLContextSpi sslContext = (SSLContextSpi) this.getField(sslSocketFactory,
"context");
return (X509TrustManager) this.getField(sslContext, "trustManager");
}
protected <T> Object getField(Object target, String name) {
@@ -81,9 +89,12 @@ public class FeignRibbonHttpClientConfigurationTests {
@Configuration
@EnableAutoConfiguration
static class FeignRibbonHttpClientConfigurationTestsApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(FeignRibbonClientRetryTests.Application.class)
.run(args);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,36 +12,37 @@
* 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.cloud.openfeign.ribbon;
import okhttp3.OkHttpClient;
import java.lang.reflect.Field;
import javax.net.ssl.HostnameVerifier;
import org.junit.Assert;
import okhttp3.OkHttpClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientRetryTests;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Ryan Baxter
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = FeignRibbonOkHttpClientConfigurationTests.FeignRibbonOkHttpClientConfigurationTestsApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"debug=true","feign.httpclient.disableSslValidation=true",
"feign.okhttp.enabled=true", "feign.httpclient.enabled=false"})
@SpringBootTest(classes = FeignRibbonOkHttpClientConfigurationTests.FeignRibbonOkHttpClientConfigurationTestsApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
"debug=true", "feign.httpclient.disableSslValidation=true",
"feign.okhttp.enabled=true", "feign.httpclient.enabled=false" })
@DirtiesContext
public class FeignRibbonOkHttpClientConfigurationTests {
@@ -50,8 +51,11 @@ public class FeignRibbonOkHttpClientConfigurationTests {
@Test
public void disableSslTest() throws Exception {
HostnameVerifier hostnameVerifier = (HostnameVerifier)this.getField(httpClient, "hostnameVerifier");
Assert.assertTrue(OkHttpClientFactory.TrustAllHostnames.class.isInstance(hostnameVerifier));
HostnameVerifier hostnameVerifier = (HostnameVerifier) this
.getField(this.httpClient, "hostnameVerifier");
assertThat(
OkHttpClientFactory.TrustAllHostnames.class.isInstance(hostnameVerifier))
.isTrue();
}
protected <T> Object getField(Object target, String name) {
@@ -64,9 +68,12 @@ public class FeignRibbonOkHttpClientConfigurationTests {
@Configuration
@EnableAutoConfiguration
static class FeignRibbonOkHttpClientConfigurationTestsApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(FeignRibbonClientRetryTests.Application.class)
.run(args);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -16,10 +16,12 @@
package org.springframework.cloud.openfeign.ribbon;
import static org.junit.Assert.assertEquals;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import feign.Request;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
@@ -33,10 +35,7 @@ import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.RequestMapping;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import feign.Request;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Spencer Gibb
@@ -56,20 +55,20 @@ public class LoadBalancerFeignClientOverrideTests {
// specific ribbon 'bar' configuration via spring bean
Request.Options barOptions = this.context.getInstance("bar",
Request.Options.class);
assertEquals(1, barOptions.connectTimeoutMillis());
assertEquals(2, barOptions.readTimeoutMillis());
assertThat(barOptions.connectTimeoutMillis()).isEqualTo(1);
assertThat(barOptions.readTimeoutMillis()).isEqualTo(2);
assertOptions(barOptions, "bar", 1, 2);
// specific ribbon 'foo' configuration via application.yml
Request.Options fooOptions = this.context.getInstance("foo",
Request.Options.class);
assertEquals(LoadBalancerFeignClient.DEFAULT_OPTIONS, fooOptions);
assertThat(fooOptions).isEqualTo(LoadBalancerFeignClient.DEFAULT_OPTIONS);
assertOptions(fooOptions, "foo", 7, 17);
// generic ribbon default configuration
Request.Options bazOptions = this.context.getInstance("baz",
Request.Options.class);
assertEquals(LoadBalancerFeignClient.DEFAULT_OPTIONS, bazOptions);
assertThat(bazOptions).isEqualTo(LoadBalancerFeignClient.DEFAULT_OPTIONS);
assertOptions(bazOptions, "baz", 3001, 60001);
}
@@ -78,44 +77,54 @@ public class LoadBalancerFeignClientOverrideTests {
LoadBalancerFeignClient client = this.context.getInstance(name,
LoadBalancerFeignClient.class);
IClientConfig config = client.getClientConfig(options, name);
assertEquals("connect was wrong for " + name, expectedConnect,
config.get(CommonClientConfigKey.ConnectTimeout, -1).intValue());
assertEquals("read was wrong for " + name, expectedRead,
config.get(CommonClientConfigKey.ReadTimeout, -1).intValue());
assertThat(config.get(CommonClientConfigKey.ConnectTimeout, -1).intValue())
.as("connect was wrong for " + name).isEqualTo(expectedConnect);
assertThat(config.get(CommonClientConfigKey.ReadTimeout, -1).intValue())
.as("read was wrong for " + name).isEqualTo(expectedRead);
}
@FeignClient(value = "foo", configuration = FooConfiguration.class)
interface FooClient {
@RequestMapping("/")
String get();
}
@FeignClient(value = "bar", configuration = BarConfiguration.class)
interface BarClient {
@RequestMapping("/")
String get();
}
@FeignClient("baz")
interface BazClient {
@RequestMapping("/")
String get();
}
@Configuration
@EnableFeignClients(clients = { FooClient.class, BarClient.class, BazClient.class })
@EnableAutoConfiguration
protected static class TestConfiguration {
}
@FeignClient(value = "foo", configuration = FooConfiguration.class)
interface FooClient {
@RequestMapping("/")
String get();
}
public static class FooConfiguration {
}
@FeignClient(value = "bar", configuration = BarConfiguration.class)
interface BarClient {
@RequestMapping("/")
String get();
}
public static class BarConfiguration {
@Bean
public Request.Options feignRequestOptions() {
return new Request.Options(1, 2);
}
}
@FeignClient("baz")
interface BazClient {
@RequestMapping("/")
String get();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,7 +12,6 @@
* 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.cloud.openfeign.ribbon;
@@ -36,7 +35,6 @@ import com.netflix.loadbalancer.Server;
import feign.Client;
import feign.Request;
import feign.Response;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@@ -69,10 +67,7 @@ import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_MAX_AUTO
import static com.netflix.client.config.DefaultClientConfigImpl.DEFAULT_MAX_AUTO_RETRIES_NEXT_SERVER;
import static feign.Request.HttpMethod.GET;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -90,13 +85,17 @@ import static org.mockito.Mockito.when;
* @author Olga Maciaszek-Sharma
*/
public class RetryableFeignLoadBalancerTests {
@Mock
private ILoadBalancer lb;
@Mock
private IClientConfig config;
private ServerIntrospector inspector = new DefaultServerIntrospector();
private Integer defaultConnectTimeout = 10000;
private Integer defaultReadTimeout = 10000;
@Before
@@ -114,31 +113,38 @@ public class RetryableFeignLoadBalancerTests {
@Test
public void executeNoFailure() throws Exception {
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
IClientConfig config = mock(IClientConfig.class);
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetries), anyInt());
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer), anyInt());
doReturn(true).when(config).get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(defaultConnectTimeout).when(config).get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(defaultReadTimeout).when(config).get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("404,502,foo, ,").when(config).getPropertyAsString(eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES),eq(""));
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer),
anyInt());
doReturn(true).when(config)
.get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(this.defaultConnectTimeout).when(config)
.get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(this.defaultReadTimeout).when(config)
.get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("404,502,foo, ,").when(config).getPropertyAsString(
eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES), eq(""));
doReturn(config).when(clientFactory).getClientConfig(eq("default"));
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(clientFactory);
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(
clientFactory);
Request feignRequest = Request.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://foo"));
Response response = Response.builder()
.status(200)
.request(feignRequest)
.headers(new HashMap<>())
.build();
doReturn(response).when(client).execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://foo"));
Response response = Response.builder().status(200).request(feignRequest)
.headers(new HashMap<>()).build();
doReturn(response).when(client).execute(any(Request.class),
any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
config, this.inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonResponse ribbonResponse = feignLb.execute(request, null);
assertEquals(200, ribbonResponse.toResponse().status());
assertThat(ribbonResponse.toResponse().status()).isEqualTo(200);
verify(client, times(1)).execute(any(Request.class), any(Request.Options.class));
}
@@ -147,48 +153,62 @@ public class RetryableFeignLoadBalancerTests {
Request feignRequest = Request.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://foo"));
doThrow(new IOException("boom")).when(client).execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, new LoadBalancedRetryFactory() {
@Override
public LoadBalancedRetryPolicy createRetryPolicy(String s, ServiceInstanceChooser serviceInstanceChooser) {
return null;
}
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://foo"));
doThrow(new IOException("boom")).when(client).execute(any(Request.class),
any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
this.config, this.inspector, new LoadBalancedRetryFactory() {
@Override
public LoadBalancedRetryPolicy createRetryPolicy(String s,
ServiceInstanceChooser serviceInstanceChooser) {
return null;
}
@Override
public RetryListener[] createRetryListeners(String service) {
return new RetryListener[0];
}
@Override
public RetryListener[] createRetryListeners(String service) {
return new RetryListener[0];
}
@Override
public BackOffPolicy createBackOffPolicy(String service) {
return null;
}
});
@Override
public BackOffPolicy createBackOffPolicy(String service) {
return null;
}
});
try {
feignLb.execute(request, null);
} catch(Exception e) {
assertThat(e, instanceOf(IOException.class));
} finally {
verify(client, times(1)).execute(any(Request.class), any(Request.Options.class));
}
catch (Exception e) {
assertThat(e).isInstanceOf(IOException.class);
}
finally {
verify(client, times(1)).execute(any(Request.class),
any(Request.Options.class));
}
}
@Test
public void executeRetry() throws Exception {
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
IClientConfig config = mock(IClientConfig.class);
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetries), anyInt());
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer), anyInt());
doReturn(true).when(config).get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(defaultConnectTimeout).when(config).get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(defaultReadTimeout).when(config).get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("").when(config).getPropertyAsString(eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES),eq(""));
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer),
anyInt());
doReturn(true).when(config)
.get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(this.defaultConnectTimeout).when(config)
.get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(this.defaultReadTimeout).when(config)
.get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("").when(config).getPropertyAsString(
eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES), eq(""));
doReturn(config).when(clientFactory).getClientConfig(eq("default"));
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
MyBackOffPolicy backOffPolicy = new MyBackOffPolicy();
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(clientFactory){
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(
clientFactory) {
@Override
public BackOffPolicy createBackOffPolicy(String service) {
return backOffPolicy;
@@ -197,36 +217,43 @@ public class RetryableFeignLoadBalancerTests {
Request feignRequest = Request.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://foo"));
Response response = Response.builder()
.status(200)
.request(feignRequest)
.headers(new HashMap<>())
.build();
doThrow(new IOException("boom")).doReturn(response).when(client).execute(any(Request.class), any(Request.Options.class));
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://foo"));
Response response = Response.builder().status(200).request(feignRequest)
.headers(new HashMap<>()).build();
doThrow(new IOException("boom")).doReturn(response).when(client)
.execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, loadBalancedRetryFactory);
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
config, this.inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonResponse ribbonResponse = feignLb.execute(request, null);
assertEquals(200, ribbonResponse.toResponse().status());
assertThat(ribbonResponse.toResponse().status()).isEqualTo(200);
verify(client, times(2)).execute(any(Request.class), any(Request.Options.class));
assertEquals(1, backOffPolicy.getCount());
assertThat(backOffPolicy.getCount()).isEqualTo(1);
}
@Test
public void executeRetryOnStatusCode() throws Exception {
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
IClientConfig config = mock(IClientConfig.class);
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetries), anyInt());
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer), anyInt());
doReturn(true).when(config).get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(defaultConnectTimeout).when(config).get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(defaultReadTimeout).when(config).get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("404").when(config).getPropertyAsString(eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES),eq(""));
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer),
anyInt());
doReturn(true).when(config)
.get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(this.defaultConnectTimeout).when(config)
.get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(this.defaultReadTimeout).when(config)
.get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("404").when(config).getPropertyAsString(
eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES), eq(""));
doReturn(config).when(clientFactory).getClientConfig(eq("default"));
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
MyBackOffPolicy backOffPolicy = new MyBackOffPolicy();
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(clientFactory){
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(
clientFactory) {
@Override
public BackOffPolicy createBackOffPolicy(String service) {
return backOffPolicy;
@@ -235,168 +262,182 @@ public class RetryableFeignLoadBalancerTests {
Request feignRequest = Request.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://foo"));
Response response = Response
.builder()
.request(feignRequest)
.status(200)
.headers(new HashMap<>())
.build();
Response fourOFourResponse = Response.builder()
.request(feignRequest)
.status(404)
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://foo"));
Response response = Response.builder().request(feignRequest).status(200)
.headers(new HashMap<>()).build();
doReturn(fourOFourResponse).doReturn(response).when(client).execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, loadBalancedRetryFactory);
Response fourOFourResponse = Response.builder().request(feignRequest).status(404)
.headers(new HashMap<>()).build();
doReturn(fourOFourResponse).doReturn(response).when(client)
.execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
config, this.inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonResponse ribbonResponse = feignLb.execute(request, null);
assertEquals(200, ribbonResponse.toResponse().status());
assertThat(ribbonResponse.toResponse().status()).isEqualTo(200);
verify(client, times(2)).execute(any(Request.class), any(Request.Options.class));
assertEquals(1, backOffPolicy.getCount());
assertThat(backOffPolicy.getCount()).isEqualTo(1);
}
@Test
@Test
public void executeRetryOnStatusCodeWithEmptyBody() throws Exception {
int retriesNextServer = 0;
when(this.config.get(MaxAutoRetriesNextServer,
DEFAULT_MAX_AUTO_RETRIES_NEXT_SERVER)).thenReturn(retriesNextServer);
doReturn(new Server("foo", 80)).when(lb).chooseServer(any());
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
IClientConfig config = mock(IClientConfig.class);
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetries), anyInt());
doReturn(retriesNextServer).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer), anyInt());
doReturn(true).when(config).get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(defaultConnectTimeout).when(config).get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(defaultReadTimeout).when(config).get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("404").when(config).getPropertyAsString(eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES),eq(""));
doReturn(config).when(clientFactory).getClientConfig(eq("default"));
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
MyBackOffPolicy backOffPolicy = new MyBackOffPolicy();
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(clientFactory){
@Override
public BackOffPolicy createBackOffPolicy(String service) {
return backOffPolicy;
}
};
Request feignRequest = Request.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://foo"));
Response response = Response.builder()
.request(feignRequest)
.status(404)
.headers(new HashMap<>())
.build();
Response fourOFourResponse = Response.builder()
.request(feignRequest)
.status(404)
.headers(new HashMap<>())
.build();
doReturn(fourOFourResponse).doReturn(response).when(client).execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonResponse ribbonResponse = feignLb.execute(request, null);
assertEquals(404, ribbonResponse.toResponse().status());
assertEquals(Integer.valueOf(0), ribbonResponse.toResponse().body().length());
verify(client, times(2)).execute(any(Request.class), any(Request.Options.class));
assertEquals(1, backOffPolicy.getCount());
int retriesNextServer = 0;
when(this.config.get(MaxAutoRetriesNextServer,
DEFAULT_MAX_AUTO_RETRIES_NEXT_SERVER)).thenReturn(retriesNextServer);
doReturn(new Server("foo", 80)).when(this.lb).chooseServer(any());
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
IClientConfig config = mock(IClientConfig.class);
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetries), anyInt());
doReturn(retriesNextServer).when(config)
.get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer), anyInt());
doReturn(true).when(config)
.get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(this.defaultConnectTimeout).when(config)
.get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(this.defaultReadTimeout).when(config)
.get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("404").when(config).getPropertyAsString(
eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES), eq(""));
doReturn(config).when(clientFactory).getClientConfig(eq("default"));
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
MyBackOffPolicy backOffPolicy = new MyBackOffPolicy();
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(
clientFactory) {
@Override
public BackOffPolicy createBackOffPolicy(String service) {
return backOffPolicy;
}
};
Request feignRequest = Request.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://foo"));
Response response = Response.builder().request(feignRequest).status(404)
.headers(new HashMap<>()).build();
Response fourOFourResponse = Response.builder().request(feignRequest).status(404)
.headers(new HashMap<>()).build();
doReturn(fourOFourResponse).doReturn(response).when(client)
.execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
config, this.inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonResponse ribbonResponse = feignLb.execute(request, null);
assertThat(ribbonResponse.toResponse().status()).isEqualTo(404);
assertThat(ribbonResponse.toResponse().body().length())
.isEqualTo(Integer.valueOf(0));
verify(client, times(2)).execute(any(Request.class), any(Request.Options.class));
assertThat(backOffPolicy.getCount()).isEqualTo(1);
}
@Test
public void getRequestSpecificRetryHandler() throws Exception {
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(clientFactory);
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(
clientFactory);
Request feignRequest = Request.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://foo"));
Response response = Response.builder()
.request(feignRequest)
.status(200)
.headers(new HashMap<>())
.build();
doReturn(response).when(client).execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, loadBalancedRetryFactory);
RequestSpecificRetryHandler retryHandler = feignLb.getRequestSpecificRetryHandler(request, config);
assertEquals(1, retryHandler.getMaxRetriesOnNextServer());
assertEquals(1, retryHandler.getMaxRetriesOnSameServer());
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://foo"));
Response response = Response.builder().request(feignRequest).status(200)
.headers(new HashMap<>()).build();
doReturn(response).when(client).execute(any(Request.class),
any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
this.config, this.inspector, loadBalancedRetryFactory);
RequestSpecificRetryHandler retryHandler = feignLb
.getRequestSpecificRetryHandler(request, this.config);
assertThat(retryHandler.getMaxRetriesOnNextServer()).isEqualTo(1);
assertThat(retryHandler.getMaxRetriesOnSameServer()).isEqualTo(1);
}
@Test
public void choose() throws Exception {
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(clientFactory);
Request feignRequest = Request
.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(
clientFactory);
Request feignRequest = Request.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://foo"));
Response response = Response.builder()
.request(feignRequest)
.status(200).headers(new HashMap<>())
.build();
doReturn(response).when(client).execute(any(Request.class), any(Request.Options.class));
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://foo"));
Response response = Response.builder().request(feignRequest).status(200)
.headers(new HashMap<>()).build();
doReturn(response).when(client).execute(any(Request.class),
any(Request.Options.class));
final Server server = new Server("foo", 80);
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(new ILoadBalancer() {
@Override
public void addServers(List<Server> list) {
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(
new ILoadBalancer() {
@Override
public void addServers(List<Server> list) {
}
}
@Override
public Server chooseServer(Object o) {
return server;
}
@Override
public Server chooseServer(Object o) {
return server;
}
@Override
public void markServerDown(Server server) {
@Override
public void markServerDown(Server server) {
}
}
@Override
public List<Server> getServerList(boolean b) {
return null;
}
@Override
public List<Server> getServerList(boolean b) {
return null;
}
@Override
public List<Server> getReachableServers() {
return null;
}
@Override
public List<Server> getReachableServers() {
return null;
}
@Override
public List<Server> getAllServers() {
return null;
}
}, config, inspector, loadBalancedRetryFactory);
@Override
public List<Server> getAllServers() {
return null;
}
}, this.config, this.inspector, loadBalancedRetryFactory);
ServiceInstance serviceInstance = feignLb.choose("foo");
assertEquals("foo", serviceInstance.getHost());
assertEquals(80, serviceInstance.getPort());
assertThat(serviceInstance.getHost()).isEqualTo("foo");
assertThat(serviceInstance.getPort()).isEqualTo(80);
}
@Test
public void retryListenerTest() throws Exception {
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
IClientConfig config = mock(IClientConfig.class);
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetries), anyInt());
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer), anyInt());
doReturn(true).when(config).get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(defaultConnectTimeout).when(config).get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(defaultReadTimeout).when(config).get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("").when(config).getPropertyAsString(eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES),eq(""));
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer),
anyInt());
doReturn(true).when(config)
.get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(this.defaultConnectTimeout).when(config)
.get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(this.defaultReadTimeout).when(config)
.get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("").when(config).getPropertyAsString(
eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES), eq(""));
doReturn(config).when(clientFactory).getClientConfig(eq("default"));
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
MyBackOffPolicy backOffPolicy = new MyBackOffPolicy();
MyRetryListener myRetryListener = new MyRetryListener();
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(clientFactory) {
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(
clientFactory) {
@Override
public RetryListener[] createRetryListeners(String service) {
return new RetryListener[]{myRetryListener};
return new RetryListener[] { myRetryListener };
}
@Override
@@ -407,41 +448,48 @@ public class RetryableFeignLoadBalancerTests {
Request feignRequest = Request.create(GET, "http://listener", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://listener"));
Response response = Response.builder()
.request(feignRequest)
.status(200)
.headers(new HashMap<>())
.build();
doThrow(new IOException("boom")).doReturn(response).when(client).execute(any(Request.class), any(Request.Options.class));
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://listener"));
Response response = Response.builder().request(feignRequest).status(200)
.headers(new HashMap<>()).build();
doThrow(new IOException("boom")).doReturn(response).when(client)
.execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, loadBalancedRetryFactory);
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
config, this.inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonResponse ribbonResponse = feignLb.execute(request, null);
assertEquals(200, ribbonResponse.toResponse().status());
assertThat(ribbonResponse.toResponse().status()).isEqualTo(200);
verify(client, times(2)).execute(any(Request.class), any(Request.Options.class));
assertEquals(1, backOffPolicy.getCount());
assertEquals(1, myRetryListener.getOnError());
assertThat(backOffPolicy.getCount()).isEqualTo(1);
assertThat(myRetryListener.getOnError()).isEqualTo(1);
}
@Test(expected = TerminatedRetryException.class)
public void retryListenerTestNoRetry() throws Exception {
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
IClientConfig config = mock(IClientConfig.class);
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetries), anyInt());
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer), anyInt());
doReturn(true).when(config).get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(defaultConnectTimeout).when(config).get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(defaultReadTimeout).when(config).get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("").when(config).getPropertyAsString(eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES),eq(""));
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer),
anyInt());
doReturn(true).when(config)
.get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(this.defaultConnectTimeout).when(config)
.get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(this.defaultReadTimeout).when(config)
.get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("").when(config).getPropertyAsString(
eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES), eq(""));
doReturn(config).when(clientFactory).getClientConfig(eq("default"));
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
MyBackOffPolicy backOffPolicy = new MyBackOffPolicy();
MyRetryListenerNotRetry myRetryListenerNotRetry = new MyRetryListenerNotRetry();
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(clientFactory){
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(
clientFactory) {
@Override
public RetryListener[] createRetryListeners(String service) {
return new RetryListener[]{myRetryListenerNotRetry};
return new RetryListener[] { myRetryListenerNotRetry };
}
@Override
@@ -452,26 +500,35 @@ public class RetryableFeignLoadBalancerTests {
Request feignRequest = Request.create(GET, "http://listener", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://listener"));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://listener"));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
config, this.inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonResponse ribbonResponse = feignLb.execute(request, null);
}
@Test
public void retryWithDefaultConstructorTest() throws Exception {
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
IClientConfig config = mock(IClientConfig.class);
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetries), anyInt());
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer), anyInt());
doReturn(true).when(config).get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(defaultConnectTimeout).when(config).get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(defaultReadTimeout).when(config).get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("").when(config).getPropertyAsString(eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES),eq(""));
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer),
anyInt());
doReturn(true).when(config)
.get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(this.defaultConnectTimeout).when(config)
.get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(this.defaultReadTimeout).when(config)
.get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("").when(config).getPropertyAsString(
eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES), eq(""));
doReturn(config).when(clientFactory).getClientConfig(eq("default"));
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
MyBackOffPolicy backOffPolicy = new MyBackOffPolicy();
RibbonLoadBalancedRetryFactory loadBalancedRetryPolicyFactory = new RibbonLoadBalancedRetryFactory(clientFactory){
RibbonLoadBalancedRetryFactory loadBalancedRetryPolicyFactory = new RibbonLoadBalancedRetryFactory(
clientFactory) {
@Override
public BackOffPolicy createBackOffPolicy(String service) {
return backOffPolicy;
@@ -480,36 +537,43 @@ public class RetryableFeignLoadBalancerTests {
Request feignRequest = Request.create(GET, "http://listener", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://listener"));
Response response = Response.builder()
.request(feignRequest)
.status(200)
.headers(new HashMap<>())
.build();
doThrow(new IOException("boom")).doReturn(response).when(client).execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, loadBalancedRetryPolicyFactory);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://listener"));
Response response = Response.builder().request(feignRequest).status(200)
.headers(new HashMap<>()).build();
doThrow(new IOException("boom")).doReturn(response).when(client)
.execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
config, this.inspector, loadBalancedRetryPolicyFactory);
FeignLoadBalancer.RibbonResponse ribbonResponse = feignLb.execute(request, null);
assertEquals(200, ribbonResponse.toResponse().status());
assertThat(ribbonResponse.toResponse().status()).isEqualTo(200);
verify(client, times(2)).execute(any(Request.class), any(Request.Options.class));
assertEquals(1, backOffPolicy.getCount());
assertThat(backOffPolicy.getCount()).isEqualTo(1);
}
@Test
public void executeRetryFail() throws Exception {
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(lb, config);
RibbonLoadBalancerContext lbContext = new RibbonLoadBalancerContext(this.lb,
this.config);
lbContext.setRetryHandler(new DefaultLoadBalancerRetryHandler(1, 0, true));
SpringClientFactory clientFactory = mock(SpringClientFactory.class);
IClientConfig config = mock(IClientConfig.class);
doReturn(1).when(config).get(eq(CommonClientConfigKey.MaxAutoRetries), anyInt());
doReturn(0).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer), anyInt());
doReturn(true).when(config).get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(defaultConnectTimeout).when(config).get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(defaultReadTimeout).when(config).get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("404").when(config).getPropertyAsString(eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES), eq(""));
doReturn(0).when(config).get(eq(CommonClientConfigKey.MaxAutoRetriesNextServer),
anyInt());
doReturn(true).when(config)
.get(eq(CommonClientConfigKey.OkToRetryOnAllOperations), eq(false));
doReturn(this.defaultConnectTimeout).when(config)
.get(eq(CommonClientConfigKey.ConnectTimeout));
doReturn(this.defaultReadTimeout).when(config)
.get(eq(CommonClientConfigKey.ReadTimeout));
doReturn("404").when(config).getPropertyAsString(
eq(RibbonLoadBalancedRetryPolicy.RETRYABLE_STATUS_CODES), eq(""));
doReturn(config).when(clientFactory).getClientConfig(eq("default"));
doReturn(lbContext).when(clientFactory).getLoadBalancerContext(any(String.class));
MyBackOffPolicy backOffPolicy = new MyBackOffPolicy();
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(clientFactory){
RibbonLoadBalancedRetryFactory loadBalancedRetryFactory = new RibbonLoadBalancedRetryFactory(
clientFactory) {
@Override
public BackOffPolicy createBackOffPolicy(String service) {
return backOffPolicy;
@@ -518,12 +582,11 @@ public class RetryableFeignLoadBalancerTests {
Request feignRequest = Request.create(GET, "http://foo", new HashMap<>(),
new byte[] {}, UTF_8);
Client client = mock(Client.class);
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(client, feignRequest, new URI("http://foo"));
Response fourOFourResponse = Response.builder()
.request(feignRequest)
.status(404)
.headers(new HashMap<>())
.body(new Response.Body() { //set content into response
FeignLoadBalancer.RibbonRequest request = new FeignLoadBalancer.RibbonRequest(
client, feignRequest, new URI("http://foo"));
Response fourOFourResponse = Response.builder().request(feignRequest).status(404)
.headers(new HashMap<>()).body(new Response.Body() { // set content into
// response
@Override
public Integer length() {
return "test".getBytes().length;
@@ -553,15 +616,17 @@ public class RetryableFeignLoadBalancerTests {
public void close() throws IOException {
}
}).build();
doReturn(fourOFourResponse).when(client).execute(any(Request.class), any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(lb, config, inspector, loadBalancedRetryFactory);
doReturn(fourOFourResponse).when(client).execute(any(Request.class),
any(Request.Options.class));
RetryableFeignLoadBalancer feignLb = new RetryableFeignLoadBalancer(this.lb,
config, this.inspector, loadBalancedRetryFactory);
FeignLoadBalancer.RibbonResponse ribbonResponse = feignLb.execute(request, null);
verify(client, times(2)).execute(any(Request.class), any(Request.Options.class));
assertEquals(1, backOffPolicy.getCount());
assertThat(backOffPolicy.getCount()).isEqualTo(1);
InputStream inputStream = ribbonResponse.toResponse().body().asInputStream();
byte[] buf = new byte[100];
int read = inputStream.read(buf);
Assert.assertThat(new String(buf, 0, read), is("test"));
assertThat(new String(buf, 0, read)).isEqualTo("test");
}
class MyBackOffPolicy implements BackOffPolicy {
@@ -574,12 +639,13 @@ public class RetryableFeignLoadBalancerTests {
}
@Override
public void backOff(BackOffContext backOffContext) throws BackOffInterruptedException {
count++;
public void backOff(BackOffContext backOffContext)
throws BackOffInterruptedException {
this.count++;
}
public int getCount() {
return count;
return this.count;
}
}
@@ -589,39 +655,48 @@ public class RetryableFeignLoadBalancerTests {
private int onError = 0;
@Override
public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
public <T, E extends Throwable> boolean open(RetryContext context,
RetryCallback<T, E> callback) {
return true;
}
@Override
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
public <T, E extends Throwable> void close(RetryContext context,
RetryCallback<T, E> callback, Throwable throwable) {
}
@Override
public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
onError++;
public <T, E extends Throwable> void onError(RetryContext context,
RetryCallback<T, E> callback, Throwable throwable) {
this.onError++;
}
public int getOnError() {
return onError;
return this.onError;
}
}
class MyRetryListenerNotRetry implements RetryListener {
@Override
public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
public <T, E extends Throwable> boolean open(RetryContext context,
RetryCallback<T, E> callback) {
return false;
}
@Override
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
public <T, E extends Throwable> void close(RetryContext context,
RetryCallback<T, E> callback, Throwable throwable) {
}
@Override
public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {}
public <T, E extends Throwable> void onError(RetryContext context,
RetryCallback<T, E> callback, Throwable throwable) {
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.openfeign.ribbon;
import java.io.ByteArrayInputStream;
@@ -33,7 +34,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.util.StreamUtils;
import static feign.Request.HttpMethod.GET;
import static org.junit.Assert.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Ryan Baxter
@@ -48,15 +49,19 @@ public class RibbonResponseStatusCodeExceptionTest {
fooValues.add("bar");
headers.put("foo", fooValues);
Request request = Request.create(GET, "http://service.com",
new HashMap<String, Collection<String>>(), new byte[]{}, Charset.defaultCharset());
new HashMap<String, Collection<String>>(), new byte[] {},
Charset.defaultCharset());
byte[] body = "foo".getBytes();
ByteArrayInputStream is = new ByteArrayInputStream(body);
Response response = Response.builder().status(200).reason("Success").request(request).body(is, body.length).headers(headers).build();
RibbonResponseStatusCodeException ex = new RibbonResponseStatusCodeException("service", response, body,
new URI(request.url()));
assertEquals(200, ex.getResponse().status());
assertEquals(request, ex.getResponse().request());
assertEquals("Success", ex.getResponse().reason());
assertEquals("foo", StreamUtils.copyToString(ex.getResponse().body().asInputStream(), Charset.defaultCharset()));
Response response = Response.builder().status(200).reason("Success")
.request(request).body(is, body.length).headers(headers).build();
RibbonResponseStatusCodeException ex = new RibbonResponseStatusCodeException(
"service", response, body, new URI(request.url()));
assertThat(ex.getResponse().status()).isEqualTo(200);
assertThat(ex.getResponse().request()).isEqualTo(request);
assertThat(ex.getResponse().reason()).isEqualTo("Success");
assertThat(StreamUtils.copyToString(ex.getResponse().body().asInputStream(),
Charset.defaultCharset())).isEqualTo("foo");
}
}
}

View File

@@ -1,19 +1,17 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* * Copyright 2013-2016 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.
* 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.cloud.openfeign.support;
@@ -21,6 +19,7 @@ package org.springframework.cloud.openfeign.support;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.util.TestPropertyValues;
@@ -30,9 +29,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Ryan Baxter
@@ -53,12 +50,18 @@ public class FeignHttpClientPropertiesTests {
@Test
public void testDefaults() {
setupContext();
assertEquals(FeignHttpClientProperties.DEFAULT_CONNECTION_TIMEOUT, getProperties().getConnectionTimeout());
assertEquals(FeignHttpClientProperties.DEFAULT_MAX_CONNECTIONS, getProperties().getMaxConnections());
assertEquals(FeignHttpClientProperties.DEFAULT_MAX_CONNECTIONS_PER_ROUTE, getProperties().getMaxConnectionsPerRoute());
assertEquals(FeignHttpClientProperties.DEFAULT_TIME_TO_LIVE, getProperties().getTimeToLive());
assertEquals(FeignHttpClientProperties.DEFAULT_DISABLE_SSL_VALIDATION, getProperties().isDisableSslValidation());
assertEquals(FeignHttpClientProperties.DEFAULT_FOLLOW_REDIRECTS, getProperties().isFollowRedirects());
assertThat(getProperties().getConnectionTimeout())
.isEqualTo(FeignHttpClientProperties.DEFAULT_CONNECTION_TIMEOUT);
assertThat(getProperties().getMaxConnections())
.isEqualTo(FeignHttpClientProperties.DEFAULT_MAX_CONNECTIONS);
assertThat(getProperties().getMaxConnectionsPerRoute())
.isEqualTo(FeignHttpClientProperties.DEFAULT_MAX_CONNECTIONS_PER_ROUTE);
assertThat(getProperties().getTimeToLive())
.isEqualTo(FeignHttpClientProperties.DEFAULT_TIME_TO_LIVE);
assertThat(getProperties().isDisableSslValidation())
.isEqualTo(FeignHttpClientProperties.DEFAULT_DISABLE_SSL_VALIDATION);
assertThat(getProperties().isFollowRedirects())
.isEqualTo(FeignHttpClientProperties.DEFAULT_FOLLOW_REDIRECTS);
}
@Test
@@ -70,16 +73,17 @@ public class FeignHttpClientPropertiesTests {
"feign.httpclient.disableSslValidation=true",
"feign.httpclient.followRedirects=false").applyTo(this.context);
setupContext();
assertEquals(2, getProperties().getMaxConnections());
assertEquals(2, getProperties().getConnectionTimeout());
assertEquals(2, getProperties().getMaxConnectionsPerRoute());
assertEquals(2L, getProperties().getTimeToLive());
assertTrue(getProperties().isDisableSslValidation());
assertFalse(getProperties().isFollowRedirects());
assertThat(getProperties().getMaxConnections()).isEqualTo(2);
assertThat(getProperties().getConnectionTimeout()).isEqualTo(2);
assertThat(getProperties().getMaxConnectionsPerRoute()).isEqualTo(2);
assertThat(getProperties().getTimeToLive()).isEqualTo(2L);
assertThat(getProperties().isDisableSslValidation()).isTrue();
assertThat(getProperties().isFollowRedirects()).isFalse();
}
private void setupContext() {
this.context.register(PropertyPlaceholderAutoConfiguration.class, TestConfiguration.class);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
this.context.refresh();
}
@@ -90,9 +94,12 @@ public class FeignHttpClientPropertiesTests {
@Configuration
@EnableConfigurationProperties
protected static class TestConfiguration {
@Bean
FeignHttpClientProperties zuulProperties() {
return new FeignHttpClientProperties() ;
return new FeignHttpClientProperties();
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,7 +12,6 @@
* 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.cloud.openfeign.support;
@@ -50,12 +49,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.http.HttpHeaders.ACCEPT;
import static org.springframework.http.HttpHeaders.CONTENT_LENGTH;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
@@ -82,110 +76,93 @@ public class SpringEncoderTests {
@Test
public void testCustomHttpMessageConverter() {
SpringEncoder encoder = this.context.getInstance("foo", SpringEncoder.class);
assertThat(encoder, is(notNullValue()));
assertThat(encoder).isNotNull();
RequestTemplate request = new RequestTemplate();
encoder.encode("hi", MyType.class, request);
Collection<String> contentTypeHeader = request.headers().get("Content-Type");
assertThat("missing content type header", contentTypeHeader, is(notNullValue()));
assertThat("missing content type header", contentTypeHeader.isEmpty(), is(false));
assertThat(contentTypeHeader).as("missing content type header").isNotNull();
assertThat(contentTypeHeader.isEmpty()).as("missing content type header")
.isFalse();
String header = contentTypeHeader.iterator().next();
assertThat("content type header is wrong", header, is("application/mytype"));
assertThat("request charset is null", request.requestCharset(), is(notNullValue()));
assertThat("request charset is wrong", request.requestCharset(), is(Charset.forName("UTF-8")));
assertThat(header).as("content type header is wrong")
.isEqualTo("application/mytype");
assertThat(request.requestCharset()).as("request charset is null").isNotNull();
assertThat(request.requestCharset()).as("request charset is wrong")
.isEqualTo(Charset.forName("UTF-8"));
}
@Test
public void testBinaryData() {
SpringEncoder encoder = this.context.getInstance("foo", SpringEncoder.class);
assertThat(encoder, is(notNullValue()));
assertThat(encoder).isNotNull();
RequestTemplate request = new RequestTemplate();
encoder.encode("hi".getBytes(), null, request);
assertThat("Request Content-Type is not octet-stream",
((List) request.headers().get(CONTENT_TYPE)).get(0),
equalTo(APPLICATION_OCTET_STREAM_VALUE));
assertThat(((List) request.headers().get(CONTENT_TYPE)).get(0))
.as("Request Content-Type is not octet-stream")
.isEqualTo(APPLICATION_OCTET_STREAM_VALUE);
}
@Test(expected = EncodeException.class)
public void testMultipartFile1() {
SpringEncoder encoder = this.context.getInstance("foo", SpringEncoder.class);
assertThat(encoder, is(notNullValue()));
assertThat(encoder).isNotNull();
RequestTemplate request = new RequestTemplate();
MultipartFile multipartFile = new MockMultipartFile("test_multipart_file", "hi".getBytes());
MultipartFile multipartFile = new MockMultipartFile("test_multipart_file",
"hi".getBytes());
encoder.encode(multipartFile, MultipartFile.class, request);
assertThat("request charset is not null", request.requestCharset(), is(nullValue()));
assertThat(request.requestCharset()).as("request charset is not null").isNull();
}
// gh-105, gh-107
@Test
public void testMultipartFile2() {
SpringEncoder encoder = this.context.getInstance("foo", SpringEncoder.class);
assertThat(encoder, is(notNullValue()));
assertThat(encoder).isNotNull();
RequestTemplate request = new RequestTemplate();
request.header(ACCEPT, MediaType.MULTIPART_FORM_DATA_VALUE);
request.header(CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE);
MultipartFile multipartFile = new MockMultipartFile("test_multipart_file", "hi".getBytes());
MultipartFile multipartFile = new MockMultipartFile("test_multipart_file",
"hi".getBytes());
encoder.encode(multipartFile, MultipartFile.class, request);
assertThat("Request Content-Type is not multipart/form-data",
(String) ((List) request.headers().get(CONTENT_TYPE)).get(0),
containsString("multipart/form-data; charset=UTF-8; boundary="));
assertThat("There is more than one Content-Type request header",
request.headers().get(CONTENT_TYPE).size(), equalTo(1));
assertThat("Request Accept header is not multipart/form-data",
((List) request.headers().get(ACCEPT)).get(0),
equalTo(MULTIPART_FORM_DATA_VALUE));
assertThat("Request Content-Length is not equal to 186",
((List) request.headers().get(CONTENT_LENGTH)).get(0),
equalTo("186"));
assertThat("Body content cannot be decoded",
new String(request.requestBody().asBytes()),
containsString("hi"));
assertThat((String) ((List) request.headers().get(CONTENT_TYPE)).get(0))
.as("Request Content-Type is not multipart/form-data")
.contains("multipart/form-data; charset=UTF-8; boundary=");
assertThat(request.headers().get(CONTENT_TYPE).size())
.as("There is more than one Content-Type request header").isEqualTo(1);
assertThat(((List) request.headers().get(ACCEPT)).get(0))
.as("Request Accept header is not multipart/form-data")
.isEqualTo(MULTIPART_FORM_DATA_VALUE);
assertThat(((List) request.headers().get(CONTENT_LENGTH)).get(0))
.as("Request Content-Length is not equal to 186").isEqualTo("186");
assertThat(new String(request.requestBody().asBytes()))
.as("Body content cannot be decoded").contains("hi");
}
class MediaTypeMatcher implements ArgumentMatcher<MediaType> {
private MediaType mediaType;
protected interface TestClient {
public MediaTypeMatcher(String type, String subtype) {
this.mediaType = new MediaType(type, subtype);
}
@Override
public boolean matches(MediaType argument) {
return this.mediaType.equals(argument);
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("MediaTypeMatcher{");
sb.append("mediaType=").append(this.mediaType);
sb.append('}');
return sb.toString();
}
}
protected static class MyType {
private String value;
public String getValue() {
return value;
return this.value;
}
public void setValue(String value) {
this.value = value;
}
}
protected interface TestClient {
}
@@ -202,7 +179,7 @@ public class SpringEncoderTests {
private static class MyHttpMessageConverter
extends AbstractGenericHttpMessageConverter<Object> {
public MyHttpMessageConverter() {
MyHttpMessageConverter() {
super(new MediaType("application", "mytype"));
}
@@ -240,7 +217,32 @@ public class SpringEncoderTests {
throws IOException, HttpMessageNotReadableException {
return null;
}
}
}
class MediaTypeMatcher implements ArgumentMatcher<MediaType> {
private MediaType mediaType;
MediaTypeMatcher(String type, String subtype) {
this.mediaType = new MediaType(type, subtype);
}
@Override
public boolean matches(MediaType argument) {
return this.mediaType.equals(argument);
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("MediaTypeMatcher{");
sb.append("mediaType=").append(this.mediaType);
sb.append('}');
return sb.toString();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -53,10 +53,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeTrue;
import static org.springframework.web.util.UriUtils.encode;
@@ -66,6 +66,7 @@ import static org.springframework.web.util.UriUtils.encode;
* @author Aram Peres
*/
public class SpringMvcContractTests {
private static final Class<?> EXECUTABLE_TYPE;
static {
@@ -81,364 +82,11 @@ public class SpringMvcContractTests {
private SpringMvcContract contract;
@Before
public void setup() {
FormattingConversionServiceFactoryBean conversionServiceFactoryBean
= new FormattingConversionServiceFactoryBean();
conversionServiceFactoryBean.afterPropertiesSet();
ConversionService conversionService = conversionServiceFactoryBean.getObject();
this.contract = new SpringMvcContract(Collections.emptyList(), conversionService);
}
@Test
public void testProcessAnnotationOnMethod_Simple() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("getTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/test/{id}", data.template().url());
assertEquals("GET", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
}
@Test
public void testProcessAnnotations_Simple() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("getTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/test/{id}", data.template().url());
assertEquals("GET", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
assertEquals("id", data.indexToName().get(0).iterator().next());
}
@Test
public void testProcessAnnotations_SimpleGetMapping() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("getMappingTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/test/{id}", data.template().url());
assertEquals("GET", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
assertEquals("id", data.indexToName().get(0).iterator().next());
}
@Test
public void testProcessAnnotations_Class_AnnotationsGetSpecificTest()
throws Exception {
Method method = TestTemplate_Class_Annotations.class
.getDeclaredMethod("getSpecificTest", String.class, String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/prepend/{classId}/test/{testId}", data.template().url());
assertEquals("GET", data.template().method());
assertEquals("classId", data.indexToName().get(0).iterator().next());
assertEquals("testId", data.indexToName().get(1).iterator().next());
}
@Test
public void testProcessAnnotations_Class_AnnotationsGetAllTests() throws Exception {
Method method = TestTemplate_Class_Annotations.class
.getDeclaredMethod("getAllTests", String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/prepend/{classId}", data.template().url());
assertEquals("GET", data.template().method());
assertEquals("classId", data.indexToName().get(0).iterator().next());
}
@Test
public void testProcessAnnotations_ExtendedInterface() throws Exception {
Method extendedMethod = TestTemplate_Extended.class.getMethod("getAllTests",
String.class);
MethodMetadata extendedData = this.contract.parseAndValidateMetadata(
extendedMethod.getDeclaringClass(), extendedMethod);
Method method = TestTemplate_Class_Annotations.class
.getDeclaredMethod("getAllTests", String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals(extendedData.template().url(), data.template().url());
assertEquals(extendedData.template().method(), data.template().method());
assertEquals(data.indexToName().get(0).iterator().next(),
data.indexToName().get(0).iterator().next());
}
@Test
public void testProcessAnnotations_SimplePost() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("postTest",
TestObject.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/", data.template().url());
assertEquals("POST", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
}
@Test
public void testProcessAnnotations_SimplePostMapping() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("postMappingTest",
TestObject.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/", data.template().url());
assertEquals("POST", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
}
@Test
public void testProcessAnnotationsOnMethod_Advanced() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest",
String.class, String.class, Integer.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/advanced/test/{id}?amount=" + encode("{amount}", UTF_8),
data.template().url());
assertEquals("PUT", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
}
@Test
public void testProcessAnnotationsOnMethod_Advanced_UnknownAnnotation()
throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest",
String.class, String.class, Integer.class);
this.contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
// Don't throw an exception and this passes
}
@Test
public void testProcessAnnotations_Advanced() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest",
String.class, String.class, Integer.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/advanced/test/{id}?amount=" + encode("{amount}", UTF_8),
data.template().url());
assertEquals("PUT", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
assertEquals("Authorization", data.indexToName().get(0).iterator().next());
assertEquals("id", data.indexToName().get(1).iterator().next());
assertEquals("amount", data.indexToName().get(2).iterator().next());
assertNotNull(data.indexToExpander().get(2));
assertEquals("{Authorization}",
data.template().headers().get("Authorization").iterator().next());
assertEquals("{amount}",
data.template().queries().get("amount").iterator().next());
}
@Test
public void testProcessAnnotations_Aliased() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest2",
String.class, Integer.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/advanced/test2?amount=" + encode("{amount}", UTF_8),
data.template().url());
assertEquals("PUT", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
assertEquals("Authorization", data.indexToName().get(0).iterator().next());
assertEquals("amount", data.indexToName().get(1).iterator().next());
assertEquals("{Authorization}",
data.template().headers().get("Authorization").iterator().next());
assertEquals("{amount}",
data.template().queries().get("amount").iterator().next());
}
@Test
public void testProcessAnnotations_DateTimeFormatParam() throws Exception {
Method method = TestTemplate_DateTimeFormatParameter.class.getDeclaredMethod(
"getTest", LocalDateTime.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
Param.Expander expander = data.indexToExpander().get(0);
assertNotNull(expander);
LocalDateTime input = LocalDateTime.of(2001, 10, 12, 23, 56, 3);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
TestTemplate_DateTimeFormatParameter.CUSTOM_PATTERN);
String expected = formatter.format(input);
assertEquals(expected, expander.expand(input));
}
@Test
public void testProcessAnnotations_NumberFormatParam() throws Exception {
Method method = TestTemplate_NumberFormatParameter.class.getDeclaredMethod(
"getTest", BigDecimal.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
Param.Expander expander = data.indexToExpander().get(0);
assertNotNull(expander);
NumberStyleFormatter formatter = new NumberStyleFormatter(
TestTemplate_NumberFormatParameter.CUSTOM_PATTERN);
BigDecimal input = BigDecimal.valueOf(1220.345);
String expected = formatter.print(input, Locale.getDefault());
String actual = expander.expand(input);
assertEquals(expected, actual);
}
@Test
public void testProcessAnnotations_Advanced2() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest");
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/advanced", data.template().url());
assertEquals("GET", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
}
@Test
public void testProcessAnnotations_Advanced3() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("getTest");
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/", data.template().url());
assertEquals("GET", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
}
@Test
public void testProcessAnnotations_ListParams() throws Exception {
Method method = TestTemplate_ListParams.class.getDeclaredMethod("getTest",
List.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/test?id=" + encode("{id}", UTF_8),
data.template().url());
assertEquals("GET", data.template().method());
assertEquals("[{id}]", data.template().queries().get("id").toString());
assertNotNull(data.indexToExpander().get(0));
}
@Test
public void testProcessAnnotations_ListParamsWithoutName() throws Exception {
Method method = TestTemplate_ListParamsWithoutName.class.getDeclaredMethod("getTest",
List.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/test?id=" + encode("{id}", UTF_8), data.template().url());
assertEquals("GET", data.template().method());
assertEquals("[{id}]", data.template().queries().get("id").toString());
assertNotNull(data.indexToExpander().get(0));
}
@Test
public void testProcessAnnotations_MapParams() throws Exception {
Method method = TestTemplate_MapParams.class.getDeclaredMethod("getTest",
Map.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/test", data.template().url());
assertEquals("GET", data.template().method());
assertNotNull(data.queryMapIndex());
assertEquals(0, data.queryMapIndex().intValue());
}
@Test
public void testProcessHeaders() throws Exception {
Method method = TestTemplate_Headers.class.getDeclaredMethod("getTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/test/{id}", data.template().url());
assertEquals("GET", data.template().method());
assertEquals("bar", data.template().headers().get("X-Foo").iterator().next());
}
@Test
public void testProcessHeadersWithoutValues() throws Exception {
Method method = TestTemplate_HeadersWithoutValues.class.getDeclaredMethod("getTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/test/{id}", data.template().url());
assertEquals("GET", data.template().method());
assertTrue(data.template().headers().isEmpty());
}
@Test
public void testProcessAnnotations_Fallback() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTestFallback",
String.class, String.class, Integer.class);
assumeTrue("does not have java 8 parameter names", hasJava8ParameterNames(method));
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/advanced/testfallback/{id}?amount=" + encode("{amount}", UTF_8), data
.template().url());
assertEquals("PUT", data.template().method());
assertEquals(MediaType.APPLICATION_JSON_VALUE,
data.template().headers().get("Accept").iterator().next());
assertEquals("Authorization", data.indexToName().get(0).iterator().next());
assertEquals("id", data.indexToName().get(1).iterator().next());
assertEquals("amount", data.indexToName().get(2).iterator().next());
assertEquals("{Authorization}",
data.template().headers().get("Authorization").iterator().next());
assertEquals("{amount}",
data.template().queries().get("amount").iterator().next());
}
/**
* For abstract (e.g. interface) methods, only Java 8 Parameter names (compiler arg
* -parameters) can supply parameter names; bytecode-based strategies use local
* variable declarations, of which there are none for abstract methods.
* @param m
* @param m method
* @return whether a parameter name was found
* @throws IllegalArgumentException if method has no parameters
*/
@@ -461,6 +109,362 @@ public class SpringMvcContractTests {
return false;
}
@Before
public void setup() {
FormattingConversionServiceFactoryBean conversionServiceFactoryBean = new FormattingConversionServiceFactoryBean();
conversionServiceFactoryBean.afterPropertiesSet();
ConversionService conversionService = conversionServiceFactoryBean.getObject();
this.contract = new SpringMvcContract(Collections.emptyList(), conversionService);
}
@Test
public void testProcessAnnotationOnMethod_Simple() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("getTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/test/{id}");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
}
@Test
public void testProcessAnnotations_Simple() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("getTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/test/{id}");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
assertThat(data.indexToName().get(0).iterator().next()).isEqualTo("id");
}
@Test
public void testProcessAnnotations_SimpleGetMapping() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("getMappingTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/test/{id}");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
assertThat(data.indexToName().get(0).iterator().next()).isEqualTo("id");
}
@Test
public void testProcessAnnotations_Class_AnnotationsGetSpecificTest()
throws Exception {
Method method = TestTemplate_Class_Annotations.class
.getDeclaredMethod("getSpecificTest", String.class, String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/prepend/{classId}/test/{testId}");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.indexToName().get(0).iterator().next()).isEqualTo("classId");
assertThat(data.indexToName().get(1).iterator().next()).isEqualTo("testId");
}
@Test
public void testProcessAnnotations_Class_AnnotationsGetAllTests() throws Exception {
Method method = TestTemplate_Class_Annotations.class
.getDeclaredMethod("getAllTests", String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/prepend/{classId}");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.indexToName().get(0).iterator().next()).isEqualTo("classId");
}
@Test
public void testProcessAnnotations_ExtendedInterface() throws Exception {
Method extendedMethod = TestTemplate_Extended.class.getMethod("getAllTests",
String.class);
MethodMetadata extendedData = this.contract.parseAndValidateMetadata(
extendedMethod.getDeclaringClass(), extendedMethod);
Method method = TestTemplate_Class_Annotations.class
.getDeclaredMethod("getAllTests", String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo(extendedData.template().url());
assertThat(data.template().method()).isEqualTo(extendedData.template().method());
assertThat(data.indexToName().get(0).iterator().next())
.isEqualTo(data.indexToName().get(0).iterator().next());
}
@Test
public void testProcessAnnotations_SimplePost() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("postTest",
TestObject.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/");
assertThat(data.template().method()).isEqualTo("POST");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
}
@Test
public void testProcessAnnotations_SimplePostMapping() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("postMappingTest",
TestObject.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/");
assertThat(data.template().method()).isEqualTo("POST");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
}
@Test
public void testProcessAnnotationsOnMethod_Advanced() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest",
String.class, String.class, Integer.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url())
.isEqualTo("/advanced/test/{id}?amount=" + encode("{amount}", UTF_8));
assertThat(data.template().method()).isEqualTo("PUT");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
}
@Test
public void testProcessAnnotationsOnMethod_Advanced_UnknownAnnotation()
throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest",
String.class, String.class, Integer.class);
this.contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
// Don't throw an exception and this passes
}
@Test
public void testProcessAnnotations_Advanced() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest",
String.class, String.class, Integer.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url())
.isEqualTo("/advanced/test/{id}?amount=" + encode("{amount}", UTF_8));
assertThat(data.template().method()).isEqualTo("PUT");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
assertThat(data.indexToName().get(0).iterator().next())
.isEqualTo("Authorization");
assertThat(data.indexToName().get(1).iterator().next()).isEqualTo("id");
assertThat(data.indexToName().get(2).iterator().next()).isEqualTo("amount");
assertThat(data.indexToExpander().get(2)).isNotNull();
assertThat(data.template().headers().get("Authorization").iterator().next())
.isEqualTo("{Authorization}");
assertThat(data.template().queries().get("amount").iterator().next())
.isEqualTo("{amount}");
}
@Test
public void testProcessAnnotations_Aliased() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest2",
String.class, Integer.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url())
.isEqualTo("/advanced/test2?amount=" + encode("{amount}", UTF_8));
assertThat(data.template().method()).isEqualTo("PUT");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
assertThat(data.indexToName().get(0).iterator().next())
.isEqualTo("Authorization");
assertThat(data.indexToName().get(1).iterator().next()).isEqualTo("amount");
assertThat(data.template().headers().get("Authorization").iterator().next())
.isEqualTo("{Authorization}");
assertThat(data.template().queries().get("amount").iterator().next())
.isEqualTo("{amount}");
}
@Test
public void testProcessAnnotations_DateTimeFormatParam() throws Exception {
Method method = TestTemplate_DateTimeFormatParameter.class
.getDeclaredMethod("getTest", LocalDateTime.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
Param.Expander expander = data.indexToExpander().get(0);
assertThat(expander).isNotNull();
LocalDateTime input = LocalDateTime.of(2001, 10, 12, 23, 56, 3);
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern(TestTemplate_DateTimeFormatParameter.CUSTOM_PATTERN);
String expected = formatter.format(input);
assertThat(expander.expand(input)).isEqualTo(expected);
}
@Test
public void testProcessAnnotations_NumberFormatParam() throws Exception {
Method method = TestTemplate_NumberFormatParameter.class
.getDeclaredMethod("getTest", BigDecimal.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
Param.Expander expander = data.indexToExpander().get(0);
assertThat(expander).isNotNull();
NumberStyleFormatter formatter = new NumberStyleFormatter(
TestTemplate_NumberFormatParameter.CUSTOM_PATTERN);
BigDecimal input = BigDecimal.valueOf(1220.345);
String expected = formatter.print(input, Locale.getDefault());
String actual = expander.expand(input);
assertThat(actual).isEqualTo(expected);
}
@Test
public void testProcessAnnotations_Advanced2() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest");
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/advanced");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
}
@Test
public void testProcessAnnotations_Advanced3() throws Exception {
Method method = TestTemplate_Simple.class.getDeclaredMethod("getTest");
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
}
@Test
public void testProcessAnnotations_ListParams() throws Exception {
Method method = TestTemplate_ListParams.class.getDeclaredMethod("getTest",
List.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/test?id=" + encode("{id}", UTF_8));
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.template().queries().get("id").toString()).isEqualTo("[{id}]");
assertThat(data.indexToExpander().get(0)).isNotNull();
}
@Test
public void testProcessAnnotations_ListParamsWithoutName() throws Exception {
Method method = TestTemplate_ListParamsWithoutName.class
.getDeclaredMethod("getTest", List.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/test?id=" + encode("{id}", UTF_8));
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.template().queries().get("id").toString()).isEqualTo("[{id}]");
assertThat(data.indexToExpander().get(0)).isNotNull();
}
@Test
public void testProcessAnnotations_MapParams() throws Exception {
Method method = TestTemplate_MapParams.class.getDeclaredMethod("getTest",
Map.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/test");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.queryMapIndex()).isNotNull();
assertThat(data.queryMapIndex().intValue()).isEqualTo(0);
}
@Test
public void testProcessHeaders() throws Exception {
Method method = TestTemplate_Headers.class.getDeclaredMethod("getTest",
String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/test/{id}");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.template().headers().get("X-Foo").iterator().next())
.isEqualTo("bar");
}
@Test
public void testProcessHeadersWithoutValues() throws Exception {
Method method = TestTemplate_HeadersWithoutValues.class
.getDeclaredMethod("getTest", String.class);
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/test/{id}");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.template().headers().isEmpty()).isTrue();
}
@Test
public void testProcessAnnotations_Fallback() throws Exception {
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTestFallback",
String.class, String.class, Integer.class);
assumeTrue("does not have java 8 parameter names",
hasJava8ParameterNames(method));
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo(
"/advanced/testfallback/{id}?amount=" + encode("{amount}", UTF_8));
assertThat(data.template().method()).isEqualTo("PUT");
assertThat(data.template().headers().get("Accept").iterator().next())
.isEqualTo(MediaType.APPLICATION_JSON_VALUE);
assertThat(data.indexToName().get(0).iterator().next())
.isEqualTo("Authorization");
assertThat(data.indexToName().get(1).iterator().next()).isEqualTo("id");
assertThat(data.indexToName().get(2).iterator().next()).isEqualTo("amount");
assertThat(data.template().headers().get("Authorization").iterator().next())
.isEqualTo("{Authorization}");
assertThat(data.template().queries().get("amount").iterator().next())
.isEqualTo("{amount}");
}
@Test
public void testProcessHeaderMap() throws Exception {
Method method = TestTemplate_HeaderMap.class.getDeclaredMethod("headerMap",
@@ -468,11 +472,11 @@ public class SpringMvcContractTests {
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/headerMap", data.template().url());
assertEquals("GET", data.template().method());
assertEquals(0, data.headerMapIndex().intValue());
assertThat(data.template().url()).isEqualTo("/headerMap");
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.headerMapIndex().intValue()).isEqualTo(0);
Map<String, Collection<String>> headers = data.template().headers();
assertEquals("{aHeader}", headers.get("aHeader").iterator().next());
assertThat(headers.get("aHeader").iterator().next()).isEqualTo("{aHeader}");
}
@Test(expected = IllegalStateException.class)
@@ -489,12 +493,12 @@ public class SpringMvcContractTests {
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/queryMap?aParam=" + encode("{aParam}", UTF_8),
data.template().url());
assertEquals("GET", data.template().method());
assertEquals(0, data.queryMapIndex().intValue());
assertThat(data.template().url())
.isEqualTo("/queryMap?aParam=" + encode("{aParam}", UTF_8));
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.queryMapIndex().intValue()).isEqualTo(0);
Map<String, Collection<String>> params = data.template().queries();
assertEquals("{aParam}", params.get("aParam").iterator().next());
assertThat(params.get("aParam").iterator().next()).isEqualTo("{aParam}");
}
@Test
@@ -504,12 +508,12 @@ public class SpringMvcContractTests {
MethodMetadata data = this.contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertEquals("/queryMapObject?aParam=" + encode("{aParam}", UTF_8),
data.template().url());
assertEquals("GET", data.template().method());
assertEquals(0, data.queryMapIndex().intValue());
assertThat(data.template().url())
.isEqualTo("/queryMapObject?aParam=" + encode("{aParam}", UTF_8));
assertThat(data.template().method()).isEqualTo("GET");
assertThat(data.queryMapIndex().intValue()).isEqualTo(0);
Map<String, Collection<String>> params = data.template().queries();
assertEquals("{aParam}", params.get("aParam").iterator().next());
assertThat(params.get("aParam").iterator().next()).isEqualTo("{aParam}");
}
@Test(expected = IllegalStateException.class)
@@ -520,6 +524,7 @@ public class SpringMvcContractTests {
}
public interface TestTemplate_Simple {
@RequestMapping(value = "/test/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<TestObject> getTest(@PathVariable("id") String id);
@@ -534,16 +539,19 @@ public class SpringMvcContractTests {
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
TestObject postMappingTest(@RequestBody TestObject object);
}
@RequestMapping("/prepend/{classId}")
public interface TestTemplate_Class_Annotations {
@RequestMapping(value = "/test/{testId}", method = RequestMethod.GET)
TestObject getSpecificTest(@PathVariable("classId") String classId,
@PathVariable("testId") String testId);
@RequestMapping(method = RequestMethod.GET)
TestObject getAllTests(@PathVariable("classId") String classId);
}
public interface TestTemplate_Extended extends TestTemplate_Class_Annotations {
@@ -551,57 +559,68 @@ public class SpringMvcContractTests {
}
public interface TestTemplate_Headers {
@RequestMapping(value = "/test/{id}", method = RequestMethod.GET, headers = "X-Foo=bar")
ResponseEntity<TestObject> getTest(@PathVariable("id") String id);
}
public interface TestTemplate_HeadersWithoutValues {
@RequestMapping(value = "/test/{id}", method = RequestMethod.GET, headers = { "X-Foo", "!X-Bar", "X-Baz!=fooBar" })
@RequestMapping(value = "/test/{id}", method = RequestMethod.GET, headers = {
"X-Foo", "!X-Bar", "X-Baz!=fooBar" })
ResponseEntity<TestObject> getTest(@PathVariable("id") String id);
}
public interface TestTemplate_ListParams {
@RequestMapping(value = "/test", method = RequestMethod.GET)
ResponseEntity<TestObject> getTest(@RequestParam("id") List<String> id);
}
public interface TestTemplate_ListParamsWithoutName {
@RequestMapping(value = "/test", method = RequestMethod.GET)
ResponseEntity<TestObject> getTest(@RequestParam List<String> id);
}
public interface TestTemplate_MapParams {
@RequestMapping(value = "/test", method = RequestMethod.GET)
ResponseEntity<TestObject> getTest(@RequestParam Map<String, String> params);
}
public interface TestTemplate_HeaderMap {
@RequestMapping(path = "/headerMap")
String headerMap(
@RequestHeader MultiValueMap<String, String> headerMap,
String headerMap(@RequestHeader MultiValueMap<String, String> headerMap,
@RequestHeader(name = "aHeader") String aHeader);
@RequestMapping(path = "/headerMapMoreThanOnce")
String headerMapMoreThanOnce(
@RequestHeader MultiValueMap<String, String> headerMap1,
@RequestHeader MultiValueMap<String, String> headerMap2);
}
public interface TestTemplate_QueryMap {
@RequestMapping(path = "/queryMap")
String queryMap(
@RequestParam MultiValueMap<String, String> queryMap,
String queryMap(@RequestParam MultiValueMap<String, String> queryMap,
@RequestParam(name = "aParam") String aParam);
@RequestMapping(path = "/queryMapMoreThanOnce")
String queryMapMoreThanOnce(
@RequestParam MultiValueMap<String, String> queryMap1,
String queryMapMoreThanOnce(@RequestParam MultiValueMap<String, String> queryMap1,
@RequestParam MultiValueMap<String, String> queryMap2);
@RequestMapping(path = "/queryMapObject")
String queryMapObject(
@SpringQueryMap TestObject queryMap,
String queryMapObject(@SpringQueryMap TestObject queryMap,
@RequestParam(name = "aParam") String aParam);
}
@JsonAutoDetect
@@ -612,7 +631,7 @@ public class SpringMvcContractTests {
@RequestMapping(path = "/test/{id}", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<TestObject> getTest(@RequestHeader("Authorization") String auth,
@PathVariable("id") String id, @RequestParam("amount") Integer amount);
@RequestMapping(path = "/test2", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<TestObject> getTest2(
@RequestHeader(name = "Authorization") String auth,
@@ -625,6 +644,7 @@ public class SpringMvcContractTests {
@RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
TestObject getTest();
}
public interface TestTemplate_DateTimeFormatParameter {
@@ -632,8 +652,9 @@ public class SpringMvcContractTests {
String CUSTOM_PATTERN = "dd-MM-yyyy HH:mm";
@RequestMapping(method = RequestMethod.GET)
String getTest(@RequestParam(name = "localDateTime")
@DateTimeFormat(pattern = CUSTOM_PATTERN) LocalDateTime localDateTime);
String getTest(
@RequestParam(name = "localDateTime") @DateTimeFormat(pattern = CUSTOM_PATTERN) LocalDateTime localDateTime);
}
public interface TestTemplate_NumberFormatParameter {
@@ -641,14 +662,16 @@ public class SpringMvcContractTests {
String CUSTOM_PATTERN = "$###,###.###";
@RequestMapping(method = RequestMethod.GET)
String getTest(@RequestParam("amount")
@NumberFormat(pattern = CUSTOM_PATTERN) BigDecimal amount);
String getTest(
@RequestParam("amount") @NumberFormat(pattern = CUSTOM_PATTERN) BigDecimal amount);
}
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
@JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE)
public class TestObject {
public String something;
public Double number;
public TestObject() {
@@ -691,10 +714,11 @@ public class SpringMvcContractTests {
@Override
public String toString() {
return new StringBuilder("TestObject{")
.append("something='").append(something).append("', ")
.append("number=").append(number)
.append("}").toString();
return new StringBuilder("TestObject{").append("something='")
.append(this.something).append("', ").append("number=")
.append(this.number).append("}").toString();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,7 +12,6 @@
* 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.cloud.openfeign.test;
@@ -57,7 +56,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -67,9 +65,8 @@ import static org.mockito.Mockito.mockingDetails;
* @author Ryan Baxter
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(properties =
{"feign.okhttp.enabled: false",
"ribbon.eureka.enabled = false"})
@SpringBootTest(properties = { "feign.okhttp.enabled: false",
"ribbon.eureka.enabled = false" })
@DirtiesContext
public class ApacheHttpClientConfigurationTests {
@@ -84,49 +81,65 @@ public class ApacheHttpClientConfigurationTests {
@Test
public void testFactories() {
assertThat(connectionManagerFactory).isInstanceOf(ApacheHttpClientConnectionManagerFactory.class);
assertThat(connectionManagerFactory).isInstanceOf(ApacheHttpClientConfigurationTestApp.MyApacheHttpClientConnectionManagerFactory.class);
assertThat(httpClientFactory).isInstanceOf(ApacheHttpClientFactory.class);
assertThat(httpClientFactory).isInstanceOf(ApacheHttpClientConfigurationTestApp.MyApacheHttpClientFactory.class);
assertThat(this.connectionManagerFactory)
.isInstanceOf(ApacheHttpClientConnectionManagerFactory.class);
assertThat(this.connectionManagerFactory).isInstanceOf(
ApacheHttpClientConfigurationTestApp.MyApacheHttpClientConnectionManagerFactory.class);
assertThat(this.httpClientFactory).isInstanceOf(ApacheHttpClientFactory.class);
assertThat(this.httpClientFactory).isInstanceOf(
ApacheHttpClientConfigurationTestApp.MyApacheHttpClientFactory.class);
}
@Test
public void testHttpClientWithFeign() {
Client delegate = feignClient.getDelegate();
assertTrue(ApacheHttpClient.class.isInstance(delegate));
ApacheHttpClient apacheHttpClient = (ApacheHttpClient)delegate;
Client delegate = this.feignClient.getDelegate();
assertThat(ApacheHttpClient.class.isInstance(delegate)).isTrue();
ApacheHttpClient apacheHttpClient = (ApacheHttpClient) delegate;
HttpClient httpClient = getField(apacheHttpClient, "client");
MockingDetails httpClientDetails = mockingDetails(httpClient);
assertTrue(httpClientDetails.isMock());
assertThat(httpClientDetails.isMock()).isTrue();
}
protected <T> T getField(Object target, String name) {
Field field = ReflectionUtils.findField(target.getClass(), name);
ReflectionUtils.makeAccessible(field);
Object value = ReflectionUtils.getField(field, target);
return (T)value;
return (T) value;
}
@SpringBootConfiguration
@EnableAutoConfiguration
@EnableFeignClients(clients = {ApacheHttpClientConfigurationTestApp.FooClient.class})
@EnableFeignClients(clients = {
ApacheHttpClientConfigurationTestApp.FooClient.class })
static class ApacheHttpClientConfigurationTestApp {
static class MyApacheHttpClientConnectionManagerFactory extends DefaultApacheHttpClientConnectionManagerFactory {
@FeignClient(name = "foo", serviceId = "foo")
interface FooClient {
}
static class MyApacheHttpClientConnectionManagerFactory
extends DefaultApacheHttpClientConnectionManagerFactory {
@Override
public HttpClientConnectionManager newConnectionManager(boolean disableSslValidation, int maxTotalConnections, int maxConnectionsPerRoute, long timeToLive, TimeUnit timeUnit, RegistryBuilder registry) {
public HttpClientConnectionManager newConnectionManager(
boolean disableSslValidation, int maxTotalConnections,
int maxConnectionsPerRoute, long timeToLive, TimeUnit timeUnit,
RegistryBuilder registry) {
return mock(PoolingHttpClientConnectionManager.class);
}
}
static class MyApacheHttpClientFactory extends DefaultApacheHttpClientFactory {
public MyApacheHttpClientFactory(HttpClientBuilder builder) {
MyApacheHttpClientFactory(HttpClientBuilder builder) {
super(builder);
}
@Override
public HttpClientBuilder createBuilder() {
CloseableHttpClient client = mock(CloseableHttpClient.class);
CloseableHttpClient client = mock(CloseableHttpClient.class);
CloseableHttpResponse response = mock(CloseableHttpResponse.class);
StatusLine statusLine = mock(StatusLine.class);
doReturn(200).when(statusLine).getStatusCode();
@@ -134,21 +147,25 @@ public class ApacheHttpClientConfigurationTests {
Header[] headers = new BasicHeader[0];
doReturn(headers).when(response).getAllHeaders();
try {
Mockito.doReturn(response).when(client).execute(any(HttpUriRequest.class));
} catch (IOException e) {
Mockito.doReturn(response).when(client)
.execute(any(HttpUriRequest.class));
}
catch (IOException e) {
e.printStackTrace();
}
HttpClientBuilder builder = mock(HttpClientBuilder.class);
Mockito.doReturn(client).when(builder).build();
return builder;
}
}
@Configuration
static class MyConfig {
@Bean
public ApacheHttpClientFactory apacheHttpClientFactory(HttpClientBuilder builder) {
public ApacheHttpClientFactory apacheHttpClientFactory(
HttpClientBuilder builder) {
return new MyApacheHttpClientFactory(builder);
}
@@ -159,9 +176,6 @@ public class ApacheHttpClientConfigurationTests {
}
@FeignClient(name="foo", serviceId = "foo")
interface FooClient {}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,7 +12,6 @@
* 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.cloud.openfeign.test;
@@ -23,11 +22,10 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
@Configuration
public class NoSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().permitAll()
.and()
.csrf().disable();
http.authorizeRequests().anyRequest().permitAll().and().csrf().disable();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,7 +12,6 @@
* 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.cloud.openfeign.test;
@@ -20,9 +19,13 @@ package org.springframework.cloud.openfeign.test;
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;
import feign.Client;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockingDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -39,21 +42,18 @@ import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockingDetails;
import feign.Client;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
/**
* @author Ryan Baxter
*/
@RunWith(SpringRunner.class)
@SpringBootTest(properties = {"feign.okhttp.enabled: true",
"spring.cloud.httpclientfactories.ok.enabled: true", "ribbon.eureka.enabled = false", "ribbon.okhttp.enabled: true",
"feign.okhttp.enabled: true", "ribbon.httpclient.enabled: false", "feign.httpclient.enabled: false"})
@SpringBootTest(properties = { "feign.okhttp.enabled: true",
"spring.cloud.httpclientfactories.ok.enabled: true",
"ribbon.eureka.enabled = false", "ribbon.okhttp.enabled: true",
"feign.okhttp.enabled: true", "ribbon.httpclient.enabled: false",
"feign.httpclient.enabled: false" })
@DirtiesContext
public class OkHttpClientConfigurationTests {
@@ -68,46 +68,41 @@ public class OkHttpClientConfigurationTests {
@Test
public void testFactories() {
assertThat(connectionPoolFactory).isInstanceOf(OkHttpClientConnectionPoolFactory.class);
assertThat(connectionPoolFactory).isInstanceOf(TestConfig.MyOkHttpClientConnectionPoolFactory.class);
assertThat(okHttpClientFactory).isInstanceOf(OkHttpClientFactory.class);
assertThat(okHttpClientFactory).isInstanceOf(TestConfig.MyOkHttpClientFactory.class);
assertThat(this.connectionPoolFactory)
.isInstanceOf(OkHttpClientConnectionPoolFactory.class);
assertThat(this.connectionPoolFactory)
.isInstanceOf(TestConfig.MyOkHttpClientConnectionPoolFactory.class);
assertThat(this.okHttpClientFactory).isInstanceOf(OkHttpClientFactory.class);
assertThat(this.okHttpClientFactory)
.isInstanceOf(TestConfig.MyOkHttpClientFactory.class);
}
@Test
public void testHttpClientWithFeign() {
Client delegate = feignClient.getDelegate();
assertTrue(feign.okhttp.OkHttpClient.class.isInstance(delegate));
feign.okhttp.OkHttpClient okHttpClient = (feign.okhttp.OkHttpClient)delegate;
Client delegate = this.feignClient.getDelegate();
assertThat(feign.okhttp.OkHttpClient.class.isInstance(delegate)).isTrue();
feign.okhttp.OkHttpClient okHttpClient = (feign.okhttp.OkHttpClient) delegate;
OkHttpClient httpClient = getField(okHttpClient, "delegate");
MockingDetails httpClientDetails = mockingDetails(httpClient);
assertTrue(httpClientDetails.isMock());
assertThat(httpClientDetails.isMock()).isTrue();
}
protected <T> T getField(Object target, String name) {
Field field = ReflectionUtils.findField(target.getClass(), name);
ReflectionUtils.makeAccessible(field);
Object value = ReflectionUtils.getField(field, target);
return (T)value;
return (T) value;
}
@FeignClient(name = "foo", serviceId = "foo")
interface FooClient {
}
@SpringBootConfiguration
@EnableAutoConfiguration
static class TestConfig {
static class MyOkHttpClientConnectionPoolFactory extends DefaultOkHttpClientConnectionPoolFactory {
@Override
public ConnectionPool create(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
return new ConnectionPool();
}
}
static class MyOkHttpClientFactory extends DefaultOkHttpClientFactory {
public MyOkHttpClientFactory(OkHttpClient.Builder builder) {
super(builder);
}
}
@Bean
public OkHttpClientConnectionPoolFactory connectionPoolFactory() {
return new MyOkHttpClientConnectionPoolFactory();
@@ -120,10 +115,28 @@ public class OkHttpClientConfigurationTests {
@Bean
public OkHttpClient client() {
return mock(OkHttpClient.class);
}
return mock(OkHttpClient.class);
}
static class MyOkHttpClientConnectionPoolFactory
extends DefaultOkHttpClientConnectionPoolFactory {
@Override
public ConnectionPool create(int maxIdleConnections, long keepAliveDuration,
TimeUnit timeUnit) {
return new ConnectionPool();
}
}
static class MyOkHttpClientFactory extends DefaultOkHttpClientFactory {
MyOkHttpClientFactory(OkHttpClient.Builder builder) {
super(builder);
}
}
}
@FeignClient(name="foo", serviceId = "foo")
interface FooClient {}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -34,17 +34,18 @@ import org.springframework.security.provisioning.InMemoryUserDetailsManager;
* @author Spencer Gibb
*/
@Configuration
@Import({NoopDiscoveryClientAutoConfiguration.class})
@Import({ NoopDiscoveryClientAutoConfiguration.class })
@AutoConfigureBefore(SecurityAutoConfiguration.class)
public class TestAutoConfiguration {
public static final String USER = "user";
public static final String PASSWORD = "{noop}password";
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
protected static class TestSecurityConfiguration extends WebSecurityConfigurerAdapter {
protected static class TestSecurityConfiguration
extends WebSecurityConfigurerAdapter {
TestSecurityConfiguration() {
super(true);
@@ -53,18 +54,18 @@ public class TestAutoConfiguration {
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername(USER).password(PASSWORD).roles("USER").build());
manager.createUser(
User.withUsername(USER).password(PASSWORD).roles("USER").build());
return manager;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// super.configure(http);
http.antMatcher("/proxy-username")
.httpBasic()
.and()
.authorizeRequests().antMatchers("/**").permitAll();
http.antMatcher("/proxy-username").httpBasic().and().authorizeRequests()
.antMatchers("/**").permitAll();
}
}
}

View File

@@ -1,20 +1,19 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* * Copyright 2013-2016 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.
* 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.cloud.openfeign.testclients;
import org.springframework.cloud.openfeign.FeignClient;
@@ -26,7 +25,8 @@ import org.springframework.web.bind.annotation.RequestMethod;
*/
@FeignClient(name = "localapp")
public interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
String getHello();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,24 +12,26 @@
* 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.cloud.openfeign.valid;
import java.util.List;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import feign.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@@ -39,20 +41,15 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import feign.Logger;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertNull;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Spencer Gibb
* @author Jakub Narloch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = FeignClientNotPrimaryTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = {
@SpringBootTest(classes = FeignClientNotPrimaryTests.Application.class, webEnvironment = RANDOM_PORT, value = {
"spring.application.name=feignclientnotprimarytest",
"logging.level.org.springframework.cloud.openfeign.valid=DEBUG",
"feign.httpclient.enabled=false", "feign.okhttp.enabled=false" })
@@ -60,8 +57,11 @@ import static org.junit.Assert.assertNull;
public class FeignClientNotPrimaryTests {
public static final String HELLO_WORLD_1 = "hello world 1";
public static final String OI_TERRA_2 = "oi terra 2";
public static final String MYHEADER1 = "myheader1";
public static final String MYHEADER2 = "myheader2";
@Value("${local.server.port}")
@@ -73,8 +73,26 @@ public class FeignClientNotPrimaryTests {
@Autowired
private List<TestClient> testClients;
@Test
public void testClientType() {
assertThat(this.testClient).as("testClient was of wrong type")
.isInstanceOf(PrimaryTestClient.class);
}
@Test
public void testClientCount() {
assertThat(this.testClients).as("testClients was wrong").hasSize(2);
}
@Test
public void testSimpleType() {
Hello hello = this.testClient.getHello();
assertThat(hello).as("hello was null").isNull();
}
@FeignClient(name = "localapp", primary = false)
protected interface TestClient {
@RequestMapping(method = RequestMethod.GET, path = "/hello")
Hello getHello();
@@ -83,8 +101,8 @@ public class FeignClientNotPrimaryTests {
@Configuration
@EnableAutoConfiguration
@RestController
@EnableFeignClients(clients = { TestClient.class} ,
defaultConfiguration = TestDefaultFeignConfig.class)
@EnableFeignClients(clients = {
TestClient.class }, defaultConfiguration = TestDefaultFeignConfig.class)
@RibbonClient(name = "localapp", configuration = LocalRibbonClientConfiguration.class)
protected static class Application {
@@ -101,53 +119,44 @@ public class FeignClientNotPrimaryTests {
}
@Test
public void testClientType() {
assertThat(this.testClient).as("testClient was of wrong type").isInstanceOf(PrimaryTestClient.class);
}
@Test
public void testClientCount() {
assertThat(this.testClients).as("testClients was wrong").hasSize(2);
}
@Test
public void testSimpleType() {
Hello hello = this.testClient.getHello();
assertNull("hello was null", hello);
}
protected static class PrimaryTestClient implements TestClient {
@Override
public Hello getHello() {
return null;
}
}
public static class Hello {
private String message;
public Hello() {}
public Hello() {
}
public Hello(String message) {
this.message = message;
}
public String getMessage() {
return message;
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
}
@Configuration
public static class TestDefaultFeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
// Load balancer with fixed server list for "local" pointing to localhost
@@ -163,4 +172,5 @@ public class FeignClientNotPrimaryTests {
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -17,20 +17,21 @@
package org.springframework.cloud.openfeign.valid;
import org.junit.Test;
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import static org.junit.Assert.assertNotNull;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Dave Syer
@@ -41,67 +42,72 @@ public class FeignClientValidationTests {
public void validNotLoadBalanced() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
GoodUrlConfiguration.class);
assertNotNull(context.getBean(GoodUrlConfiguration.Client.class));
assertThat(context.getBean(GoodUrlConfiguration.Client.class)).isNotNull();
context.close();
}
@Configuration
@Import({FeignAutoConfiguration.class, HttpClientConfiguration.class})
@EnableFeignClients(clients = GoodUrlConfiguration.Client.class)
protected static class GoodUrlConfiguration {
@FeignClient(name="example", url="http://example.com")
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
@Deprecated
String get();
}
}
@Test
public void validPlaceholder() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
PlaceholderUrlConfiguration.class);
assertNotNull(context.getBean(PlaceholderUrlConfiguration.Client.class));
assertThat(context.getBean(PlaceholderUrlConfiguration.Client.class)).isNotNull();
context.close();
}
@Configuration
@Import({FeignAutoConfiguration.class, HttpClientConfiguration.class})
@EnableFeignClients(clients = PlaceholderUrlConfiguration.Client.class)
protected static class PlaceholderUrlConfiguration {
@FeignClient(name="example", url="${feignClient.url:http://example.com}")
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
@Deprecated
String get();
}
}
@Test
public void validLoadBalanced() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
LoadBalancerAutoConfiguration.class,
RibbonAutoConfiguration.class,
LoadBalancerAutoConfiguration.class, RibbonAutoConfiguration.class,
FeignRibbonClientAutoConfiguration.class,
GoodServiceIdConfiguration.class);
assertNotNull(context.getBean(GoodServiceIdConfiguration.Client.class));
assertThat(context.getBean(GoodServiceIdConfiguration.Client.class)).isNotNull();
context.close();
}
@Configuration
@Import({FeignAutoConfiguration.class, HttpClientConfiguration.class})
@Import({ FeignAutoConfiguration.class, HttpClientConfiguration.class })
@EnableFeignClients(clients = GoodUrlConfiguration.Client.class)
protected static class GoodUrlConfiguration {
@FeignClient(name = "example", url = "http://example.com")
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
@Deprecated
String get();
}
}
@Configuration
@Import({ FeignAutoConfiguration.class, HttpClientConfiguration.class })
@EnableFeignClients(clients = PlaceholderUrlConfiguration.Client.class)
protected static class PlaceholderUrlConfiguration {
@FeignClient(name = "example", url = "${feignClient.url:http://example.com}")
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
@Deprecated
String get();
}
}
@Configuration
@Import({ FeignAutoConfiguration.class, HttpClientConfiguration.class })
@EnableFeignClients(clients = GoodServiceIdConfiguration.Client.class)
protected static class GoodServiceIdConfiguration {
@FeignClient("foo")
interface Client {
@RequestMapping(method = RequestMethod.GET, value = "/")
@Deprecated
String get();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2015 the original author or authors.
* Copyright 2013-2019 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.
@@ -18,19 +18,23 @@ package org.springframework.cloud.openfeign.valid;
import java.util.Objects;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import feign.Client;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -46,18 +50,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import feign.Client;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Spencer Gibb
@@ -81,25 +74,63 @@ public class FeignHttpClientTests {
@Autowired
private UserClient userClient;
@Test
public void testSimpleType() {
Hello hello = this.testClient.getHello();
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match")
.isEqualTo(new Hello("hello world 1"));
}
@Test
public void testPatch() {
ResponseEntity<Void> response = this.testClient.patchHello(new Hello("foo"));
assertThat(response).isNotNull();
String header = response.getHeaders().getFirst("X-Hello");
assertThat(header).isEqualTo("hello world patch");
}
@Test
public void testFeignClientType() throws IllegalAccessException {
assertThat(this.feignClient).isInstanceOf(LoadBalancerFeignClient.class);
LoadBalancerFeignClient client = (LoadBalancerFeignClient) this.feignClient;
Client delegate = client.getDelegate();
assertThat(delegate).isInstanceOf(feign.httpclient.ApacheHttpClient.class);
}
@Test
public void testFeignInheritanceSupport() {
assertThat(this.userClient).as("UserClient was null").isNotNull();
final User user = this.userClient.getUser(1);
assertThat(user).as("Returned user was null").isNotNull();
assertThat(new User("John Smith")).as("Users were different").isEqualTo(user);
}
@FeignClient("localapp")
protected interface TestClient extends BaseTestClient {
}
protected interface BaseTestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello", produces = MediaType.APPLICATION_JSON_VALUE)
Hello getHello();
@RequestMapping(method = RequestMethod.PATCH, value = "/hellop", consumes = "application/json")
ResponseEntity<Void> patchHello(Hello hello);
}
protected interface UserService {
@RequestMapping(method = RequestMethod.GET, value = "/users/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
User getUser(@PathVariable("id") long id);
}
@FeignClient("localapp1")
protected interface UserClient extends UserService {
}
@Configuration
@@ -108,8 +139,7 @@ public class FeignHttpClientTests {
@EnableFeignClients(clients = { TestClient.class, UserClient.class })
@RibbonClients({
@RibbonClient(name = "localapp", configuration = LocalRibbonClientConfiguration.class),
@RibbonClient(name = "localapp1", configuration = LocalRibbonClientConfiguration.class)
})
@RibbonClient(name = "localapp1", configuration = LocalRibbonClientConfiguration.class) })
@Import(NoSecurityConfiguration.class)
protected static class Application implements UserService {
@@ -120,12 +150,14 @@ public class FeignHttpClientTests {
@RequestMapping(method = RequestMethod.PATCH, value = "/hellop")
public ResponseEntity<Void> patchHello(@RequestBody Hello hello,
@RequestHeader("Content-Length") int contentLength) {
@RequestHeader("Content-Length") int contentLength) {
if (contentLength <= 0) {
throw new IllegalArgumentException("Invalid Content-Length "+ contentLength);
throw new IllegalArgumentException(
"Invalid Content-Length " + contentLength);
}
if (!hello.getMessage().equals("foo")) {
throw new IllegalArgumentException("Invalid Hello: " + hello.getMessage());
throw new IllegalArgumentException(
"Invalid Hello: " + hello.getMessage());
}
return ResponseEntity.ok().header("X-Hello", "hello world patch").build();
}
@@ -137,48 +169,19 @@ public class FeignHttpClientTests {
}
@Test
public void testSimpleType() {
Hello hello = this.testClient.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}
@Test
public void testPatch() {
ResponseEntity<Void> response = this.testClient.patchHello(new Hello("foo"));
assertThat(response, is(notNullValue()));
String header = response.getHeaders().getFirst("X-Hello");
assertThat(header, equalTo("hello world patch"));
}
@Test
public void testFeignClientType() throws IllegalAccessException {
assertThat(this.feignClient, is(instanceOf(LoadBalancerFeignClient.class)));
LoadBalancerFeignClient client = (LoadBalancerFeignClient) this.feignClient;
Client delegate = client.getDelegate();
assertThat(delegate, is(instanceOf(feign.httpclient.ApacheHttpClient.class)));
}
@Test
public void testFeignInheritanceSupport() {
assertNotNull("UserClient was null", this.userClient);
final User user = this.userClient.getUser(1);
assertNotNull("Returned user was null", user);
assertEquals("Users were different", user, new User("John Smith"));
}
public static class Hello {
private String message;
public Hello() {}
public Hello() {
}
public Hello(String message) {
this.message = message;
}
public String getMessage() {
return message;
return this.message;
}
public void setMessage(String message) {
@@ -187,29 +190,36 @@ public class FeignHttpClientTests {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Hello that = (Hello) o;
return Objects.equals(message, that.message);
return Objects.equals(this.message, that.message);
}
@Override
public int hashCode() {
return Objects.hash(message);
return Objects.hash(this.message);
}
}
public static class User {
private String name;
public User() {}
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
return this.name;
}
public void setName(String name) {
@@ -218,16 +228,21 @@ public class FeignHttpClientTests {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
User that = (User) o;
return Objects.equals(name, that.name);
return Objects.equals(this.name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
return Objects.hash(this.name);
}
}
// Load balancer with fixed server list for "local" pointing to localhost
@@ -243,4 +258,5 @@ public class FeignHttpClientTests {
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2019 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.
@@ -12,24 +12,29 @@
* 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.cloud.openfeign.valid;
import java.util.Objects;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import feign.Client;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -44,20 +49,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import feign.Client;
import java.util.Objects;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Spencer Gibb
@@ -82,25 +74,63 @@ public class FeignOkHttpTests {
@Autowired
private UserClient userClient;
@Test
public void testSimpleType() {
Hello hello = this.testClient.getHello();
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match")
.isEqualTo(new Hello("hello world 1"));
}
@Test
public void testPatch() {
ResponseEntity<Void> response = this.testClient.patchHello(new Hello("foo"));
assertThat(response).isNotNull();
String header = response.getHeaders().getFirst("X-Hello");
assertThat(header).isEqualTo("hello world patch");
}
@Test
public void testFeignClientType() throws IllegalAccessException {
assertThat(this.feignClient).isInstanceOf(LoadBalancerFeignClient.class);
LoadBalancerFeignClient client = (LoadBalancerFeignClient) this.feignClient;
Client delegate = client.getDelegate();
assertThat(delegate).isInstanceOf(feign.okhttp.OkHttpClient.class);
}
@Test
public void testFeignInheritanceSupport() {
assertThat(this.userClient).as("UserClient was null").isNotNull();
final User user = this.userClient.getUser(1);
assertThat(user).as("Returned user was null").isNotNull();
assertThat(new User("John Smith")).as("Users were different").isEqualTo(user);
}
@FeignClient("localapp")
protected interface TestClient extends BaseTestClient {
}
protected interface BaseTestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
Hello getHello();
@RequestMapping(method = RequestMethod.PATCH, value = "/hellop", consumes = "application/json")
ResponseEntity<Void> patchHello(Hello hello);
}
protected interface UserService {
@RequestMapping(method = RequestMethod.GET, value = "/users/{id}")
User getUser(@PathVariable("id") long id);
}
@FeignClient("localapp1")
protected interface UserClient extends UserService {
}
@Configuration
@@ -109,8 +139,7 @@ public class FeignOkHttpTests {
@EnableFeignClients(clients = { TestClient.class, UserClient.class })
@RibbonClients({
@RibbonClient(name = "localapp", configuration = LocalRibbonClientConfiguration.class),
@RibbonClient(name = "localapp1", configuration = LocalRibbonClientConfiguration.class)
})
@RibbonClient(name = "localapp1", configuration = LocalRibbonClientConfiguration.class) })
@Import(NoSecurityConfiguration.class)
protected static class Application implements UserService {
@@ -123,10 +152,12 @@ public class FeignOkHttpTests {
public ResponseEntity<Void> patchHello(@RequestBody Hello hello,
@RequestHeader("Content-Length") int contentLength) {
if (contentLength <= 0) {
throw new IllegalArgumentException("Invalid Content-Length "+ contentLength);
throw new IllegalArgumentException(
"Invalid Content-Length " + contentLength);
}
if (!hello.getMessage().equals("foo")) {
throw new IllegalArgumentException("Invalid Hello: " + hello.getMessage());
throw new IllegalArgumentException(
"Invalid Hello: " + hello.getMessage());
}
return ResponseEntity.ok().header("X-Hello", "hello world patch").build();
}
@@ -138,38 +169,8 @@ public class FeignOkHttpTests {
}
@Test
public void testSimpleType() {
Hello hello = this.testClient.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}
@Test
public void testPatch() {
ResponseEntity<Void> response = this.testClient.patchHello(new Hello("foo"));
assertThat(response, is(notNullValue()));
String header = response.getHeaders().getFirst("X-Hello");
assertThat(header, equalTo("hello world patch"));
}
@Test
public void testFeignClientType() throws IllegalAccessException {
assertThat(this.feignClient, is(instanceOf(LoadBalancerFeignClient.class)));
LoadBalancerFeignClient client = (LoadBalancerFeignClient) this.feignClient;
Client delegate = client.getDelegate();
assertThat(delegate, is(instanceOf(feign.okhttp.OkHttpClient.class)));
}
@Test
public void testFeignInheritanceSupport() {
assertNotNull("UserClient was null", this.userClient);
final User user = this.userClient.getUser(1);
assertNotNull("Returned user was null", user);
assertEquals("Users were different", user, new User("John Smith"));
}
public static class Hello {
private String message;
public Hello() {
@@ -180,7 +181,7 @@ public class FeignOkHttpTests {
}
public String getMessage() {
return message;
return this.message;
}
public void setMessage(String message) {
@@ -189,19 +190,25 @@ public class FeignOkHttpTests {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Hello that = (Hello) o;
return Objects.equals(message, that.message);
return Objects.equals(this.message, that.message);
}
@Override
public int hashCode() {
return Objects.hash(message);
return Objects.hash(this.message);
}
}
public static class User {
private String name;
public User() {
@@ -212,7 +219,7 @@ public class FeignOkHttpTests {
}
public String getName() {
return name;
return this.name;
}
public void setName(String name) {
@@ -221,16 +228,21 @@ public class FeignOkHttpTests {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
User that = (User) o;
return Objects.equals(name, that.name);
return Objects.equals(this.name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
return Objects.hash(this.name);
}
}
// Load balancer with fixed server list for "local" pointing to localhost
@@ -246,4 +258,5 @@ public class FeignOkHttpTests {
}
}
}

View File

@@ -1,33 +1,35 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* * Copyright 2013-2016 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.
* 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.cloud.openfeign.valid.scanning;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
import org.springframework.cloud.openfeign.testclients.TestClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -37,17 +39,14 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Ryan Baxter
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = FeignClientEnvVarTests.Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, value = {
@SpringBootTest(classes = FeignClientEnvVarTests.Application.class, webEnvironment = RANDOM_PORT, value = {
"spring.application.name=feignclienttest", "feign.httpclient.enabled=false",
"basepackage=org.springframework.cloud.openfeign.testclients" })
@DirtiesContext
@@ -59,22 +58,23 @@ public class FeignClientEnvVarTests {
@Test
public void testSimpleType() {
String hello = this.testClient.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", "hello world 1", hello);
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match").isEqualTo("hello world 1");
}
@Configuration
@EnableAutoConfiguration
@RestController
@EnableFeignClients(basePackages = {"${basepackage}"})
@EnableFeignClients(basePackages = { "${basepackage}" })
@RibbonClient(name = "localapp", configuration = LocalRibbonClientConfiguration.class)
@Import(NoSecurityConfiguration.class)
protected static class Application {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public String getHello() {
return "hello world 1";
}
}
// Load balancer with fixed server list for "local" pointing to localhost
@@ -90,4 +90,5 @@ public class FeignClientEnvVarTests {
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2018 the original author or authors.
* Copyright 2013-2019 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.
@@ -26,7 +26,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.openfeign.EnableFeignClients;
@@ -41,14 +40,14 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
* @author Spencer Gibb
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = FeignClientScanningTests.Application.class, webEnvironment = WebEnvironment.RANDOM_PORT, value = {
@SpringBootTest(classes = FeignClientScanningTests.Application.class, webEnvironment = RANDOM_PORT, value = {
"spring.application.name=feignclienttest", "feign.httpclient.enabled=false" })
@DirtiesContext
public class FeignClientScanningTests {
@@ -66,16 +65,34 @@ public class FeignClientScanningTests {
@SuppressWarnings("unused")
private Client feignClient;
@Test
public void testSimpleType() {
String hello = this.testClient.getHello();
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match").isEqualTo("hello world 1");
}
@Test
public void testSimpleTypeByKey() {
String hello = this.testClientByKey.getHello();
assertThat(hello).as("hello was null").isNotNull();
assertThat(hello).as("first hello didn't match").isEqualTo("hello world 1");
}
@FeignClient("localapp123")
protected interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
String getHello();
}
@FeignClient("${feignClient.localappName}")
protected interface TestClientByKey {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
String getHello();
}
@Configuration
@@ -85,6 +102,7 @@ public class FeignClientScanningTests {
@RibbonClients(defaultConfiguration = LocalRibbonClientConfiguration.class)
@Import(NoSecurityConfiguration.class)
protected static class Application {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public String getHello() {
return "hello world 1";
@@ -92,20 +110,6 @@ public class FeignClientScanningTests {
}
@Test
public void testSimpleType() {
String hello = this.testClient.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", "hello world 1", hello);
}
@Test
public void testSimpleTypeByKey() {
String hello = this.testClientByKey.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", "hello world 1", hello);
}
// Load balancer with fixed server list for "local" pointing to localhost
@Configuration
public static class LocalRibbonClientConfiguration {
@@ -119,4 +123,5 @@ public class FeignClientScanningTests {
}
}
}

View File

@@ -1,21 +1,15 @@
# This configuration used by test class FeignClientUsingPropertiesTests
logging.level.org.springframework.cloud.openfeign=debug
feign.client.default-to-properties=true
feign.client.default-config=default
feign.client.config.default.connectTimeout=5000
feign.client.config.default.readTimeout=5000
feign.client.config.default.loggerLevel=full
feign.client.config.default.errorDecoder=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.DefaultErrorDecoder
feign.client.config.default.retryer=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.NoRetryer
feign.client.config.default.decode404=true
feign.client.config.foo.requestInterceptors[0]=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.FooRequestInterceptor
feign.client.config.foo.requestInterceptors[1]=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.BarRequestInterceptor
feign.client.config.bar.connectTimeout=1000
feign.client.config.bar.readTimeout=1000
feign.client.config.form.encoder=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.FormEncoder
feign.client.config.form.encoder=org.springframework.cloud.openfeign.FeignClientUsingPropertiesTests.FormEncoder