Merge remote-tracking branch 'origin/2.0.x'
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.openfeign;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.ClosedFileSystemException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Sven Döring
|
||||
*/
|
||||
public class FeignClientBuilderTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private FeignClientBuilder feignClientBuilder;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private static Object getDefaultValueFromFeignClientAnnotation(
|
||||
final String methodName) {
|
||||
final Method method = ReflectionUtils.findMethod(FeignClient.class, methodName);
|
||||
return method.getDefaultValue();
|
||||
}
|
||||
|
||||
private static void assertFactoryBeanField(final FeignClientBuilder.Builder builder,
|
||||
final String fieldName, final Object expectedValue) {
|
||||
final Field factoryBeanField = ReflectionUtils
|
||||
.findField(FeignClientBuilder.Builder.class, "feignClientFactoryBean");
|
||||
ReflectionUtils.makeAccessible(factoryBeanField);
|
||||
final FeignClientFactoryBean factoryBean = (FeignClientFactoryBean) ReflectionUtils
|
||||
.getField(factoryBeanField, builder);
|
||||
|
||||
final Field field = ReflectionUtils.findField(FeignClientFactoryBean.class,
|
||||
fieldName);
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
final Object value = ReflectionUtils.getField(field, factoryBean);
|
||||
Assert.assertEquals("Expected value for the field '" + fieldName + "':",
|
||||
expectedValue, value);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.applicationContext = Mockito.mock(ApplicationContext.class);
|
||||
this.feignClientBuilder = new FeignClientBuilder(applicationContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safetyCheckForNewFieldsOnTheFeignClientAnnotation() {
|
||||
final List<String> methodNames = new ArrayList();
|
||||
for (final Method method : FeignClient.class.getMethods()) {
|
||||
methodNames.add(method.getName());
|
||||
}
|
||||
methodNames.removeAll(
|
||||
Arrays.asList("annotationType", "value", "serviceId", "qualifier",
|
||||
"configuration", "primary", "equals", "hashCode", "toString"));
|
||||
Collections.sort(methodNames);
|
||||
// If this safety check fails the Builder has to be updated.
|
||||
// (1) Either a field was removed from the FeignClient annotation and so it has to
|
||||
// be removed
|
||||
// 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("decode404", "fallback",
|
||||
"fallbackFactory", "name", "path", "url"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forType_preinitializedBuilder() {
|
||||
// when:
|
||||
final FeignClientBuilder.Builder builder = feignClientBuilder
|
||||
.forType(FeignClientBuilderTests.class, "TestClient");
|
||||
|
||||
// then:
|
||||
assertFactoryBeanField(builder, "applicationContext", applicationContext);
|
||||
assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
|
||||
assertFactoryBeanField(builder, "name", "TestClient");
|
||||
|
||||
// and:
|
||||
assertFactoryBeanField(builder, "url",
|
||||
getDefaultValueFromFeignClientAnnotation("url"));
|
||||
assertFactoryBeanField(builder, "path",
|
||||
getDefaultValueFromFeignClientAnnotation("path"));
|
||||
assertFactoryBeanField(builder, "decode404",
|
||||
getDefaultValueFromFeignClientAnnotation("decode404"));
|
||||
assertFactoryBeanField(builder, "fallback",
|
||||
getDefaultValueFromFeignClientAnnotation("fallback"));
|
||||
assertFactoryBeanField(builder, "fallbackFactory",
|
||||
getDefaultValueFromFeignClientAnnotation("fallbackFactory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forType_allFieldsSetOnBuilder() {
|
||||
// when:
|
||||
final FeignClientBuilder.Builder builder = feignClientBuilder
|
||||
.forType(FeignClientBuilderTests.class, "TestClient").decode404(true)
|
||||
.fallback(Object.class).fallbackFactory(Object.class).path("Path/")
|
||||
.url("Url/");
|
||||
|
||||
// then:
|
||||
assertFactoryBeanField(builder, "applicationContext", applicationContext);
|
||||
assertFactoryBeanField(builder, "type", FeignClientBuilderTests.class);
|
||||
assertFactoryBeanField(builder, "name", "TestClient");
|
||||
|
||||
// and:
|
||||
assertFactoryBeanField(builder, "url", "http://Url/");
|
||||
assertFactoryBeanField(builder, "path", "/Path");
|
||||
assertFactoryBeanField(builder, "decode404", true);
|
||||
assertFactoryBeanField(builder, "fallback", Object.class);
|
||||
assertFactoryBeanField(builder, "fallbackFactory", Object.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forType_build() {
|
||||
// given:
|
||||
Mockito.when(applicationContext.getBean(FeignContext.class))
|
||||
.thenThrow(new ClosedFileSystemException()); // throw an unusual exception
|
||||
// in the
|
||||
// FeignClientFactoryBean
|
||||
final FeignClientBuilder.Builder builder = 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));
|
||||
builder.build();
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,11 @@ 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.openfeign.FeignClientBuilder;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
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;
|
||||
@@ -66,12 +69,24 @@ public class FeignClientTests {
|
||||
@Autowired
|
||||
private org.springframework.cloud.openfeign.beans.extra.TestClient extraClient;
|
||||
|
||||
@Qualifier("build-by-builder")
|
||||
@Autowired
|
||||
private TestClient buildByBuilder;
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
@EnableFeignClients
|
||||
@Import(FeignClientBuilder.class)
|
||||
protected static class Application {
|
||||
|
||||
@Bean("build-by-builder")
|
||||
public TestClient buildByBuilder(final FeignClientBuilder feignClientBuilder) {
|
||||
return feignClientBuilder
|
||||
.forType(TestClient.class, "builderapp")
|
||||
.build();
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||
public Hello getHello() {
|
||||
return new Hello("hello world 1");
|
||||
@@ -112,7 +127,7 @@ public class FeignClientTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnnotations() throws Exception {
|
||||
public void testAnnotations() {
|
||||
Map<String, Object> beans = this.context
|
||||
.getBeansWithAnnotation(FeignClient.class);
|
||||
assertTrue("Wrong clients: " + beans,
|
||||
@@ -122,13 +137,31 @@ public class FeignClientTests {
|
||||
@Test
|
||||
public void testClient() {
|
||||
assertNotNull("testClient was null", this.testClient);
|
||||
assertNotNull("testClient was null", this.extraClient);
|
||||
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 {
|
||||
}
|
||||
|
||||
@@ -18,9 +18,11 @@ package org.springframework.cloud.openfeign.beans;
|
||||
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.cloud.openfeign.beans.FeignClientTests.Hello;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
@Primary
|
||||
@FeignClient(value = "localapp")
|
||||
public interface TestClient {
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/hello")
|
||||
|
||||
Reference in New Issue
Block a user