Reputation: 1629
I am using spring boot 2.4.2 and spring cloud 2020.0.1. I am using openfeign with hystrix as circuit breaker. I am using Eureka for service discovery. The functionality works as expected but I am not able to get the tests working. It throws an exception as
[503] during [GET] to [http://simple-helloworld-api/api/v1/greet/Test?error=false] [HelloWorldFeignClient#greeting(String,Boolean)]: [Load balancer does not contain an instance for the service simple-helloworld-api]
Dependencies in build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-hystrix', version: '2.2.7.RELEASE'
implementation group: 'io.github.openfeign', name: 'feign-hystrix', version: '11.0'
implementation group: 'io.github.openfeign', name: 'feign-httpclient', version: '11.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation "com.github.tomakehurst:wiremock:2.26.3"
testImplementation group: 'io.github.openfeign', name: 'feign-ribbon', version: '11.0'
}
Feign Client
@FeignClient(name = "${feign.name.helloWorldApi}",
configuration = HelloWorldFeignClientConfiguration.class,
fallbackFactory = HelloWorldFeignClientFallbackFactory.class)
public interface HelloWorldFeignClient {
@GetMapping("${helloWorldApi.baseUrl}" + "greet/{name}")
String greeting(@PathVariable("name") String name, @RequestParam(name = "error", required = false) Boolean error);
}
HelloWorldFeignClientFallbackFactory is imported from org.springframework.cloud.openfeign.FallbackFactory
and not from feign.hystrix
.
Test class
@SpringBootTest(classes = {HelloWorldFeignClientTest.FeignConfig.class},
properties = {"eureka.client.enabled=false", "feign.circuitbreaker.enabled=true"},
webEnvironment = WebEnvironment.RANDOM_PORT)
class LoadBalancedHelloWorldFeignClientTest {
private static WireMockServer wireMockServer;
@Autowired
private HelloWorldFeignClient helloWorldFeignClient;
@BeforeAll
static void setUp() {
wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig().dynamicPort());
wireMockServer.start();
}
@AfterAll
static void tearDown() {
wireMockServer.stop();
wireMockServer = null;
}
@Test
void testHelloWorldFeign_Success_ReturnGreetingMessage() {
//Arrange
wireMockServer.stubFor(get(urlPathEqualTo("/api/v1/greet/Test"))
.willReturn(aResponse()
.withStatus(HttpStatus.OK.value())
.withHeader("Content-Type", MediaType.TEXT_PLAIN_VALUE)
.withBody("Hello!! Test")));
//Act
String message = helloWorldFeignClient.greeting("Test", false);
//Assert
assertThat(message).isNotNull();
}
@Test
void testHelloWorldFeign_Fail_ReturnNull() {
wireMockServer.stubFor(get(urlPathEqualTo("/api/v1/greet/.*"))
.willReturn(aResponse().withStatus(501)));
String message = helloWorldFeignClient.greeting("Test", true);
//Hystrix fallback implementation will return null
assertThat(message).isNull();
}
@EnableFeignClients(clients = HelloWorldFeignClient.class)
@Configuration
@EnableAutoConfiguration
@RibbonClient(name = "simple-helloworld-api", configuration = LoadBalancedHelloWorldFeignClientTest.RibbonConfig.class)
static class FeignConfig {
@Bean
public HelloWorldFeignClientFallbackFactory helloWorldFeignClientFallbackFactory() {
return new HelloWorldFeignClientFallbackFactory();
}
}
@Configuration
static class RibbonConfig {
@Bean
public ServerList<Server> serverList() {
return new StaticServerList<>(new Server("localhost", wireMockServer.port()));
}
}
}
Can someone please help me out here? I have pushed the sample project to https://github.com/sbhambani/simple-helloworld-api-client.
Upvotes: 0
Views: 1086
Reputation: 1629
Finally, I have been able to fix the issue with test cases. Instance information needs to be set in SimpleDiscoveryProperties
.
Set instance information
@BeforeEach
void addServiceInstance() {
DefaultServiceInstance defaultServiceInstance = new DefaultServiceInstance();
defaultServiceInstance.setServiceId("simple-helloworld-api");
defaultServiceInstance.setHost("localhost");
defaultServiceInstance.setPort(wireMockServer.port());
Map<String, List<DefaultServiceInstance>> instances = new HashMap<>();
instances.put("simple-helloworld-api", Collections.singletonList(defaultServiceInstance));
simpleDiscoveryProperties.setInstances(instances);
}
@AfterEach
void removeServiceInstance() {
simpleDiscoveryProperties.getInstances().clear();
}
Upvotes: 1