Spring Boot — Unit test a Feign Client

Sumant Rana
3 min readMay 30, 2020

--

I am dedicating this article to my dear friend and colleague Li Gang who helped me devise this mechanism to test a Feign Client (using name parameter and no target URL) without having the need to spin up the real target service.

To get hold of the code referred to in this article please visit the repository @ https://github.com/sumantrana/FeignClientExample.git

Feign Client

Feign client provides a declarative mechanism for the clients to consume rest based APIs. Spring Cloud integrates Feign with Ribbon and Eureka to provide service discovery as well as inherent client side load balancing.

For more details on Feign client and how spring integrates it with Eureka and Ribbon please refer to the following link https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html.

Prerequisites:

  • Spring Boot
  • Open Feign
  • Netflix Ribbon

Create a Feign Client

Create a simple feign client calling a remote method hello on a remote service identified by name test. We want to test this Feign client without the creation of target service.

If we define a url as a parameter of the FeignClient annotation, then we can simply use wiremock or equivalent library to spin up a mock endpoint (corresponding to that url) and test the client against it. But in this case we want to be able to use name instead of the url. For an example of the URL based testing, as well as for the name based testing (described below) please refer to the gitlab URL mentioned above.

@FeignClient(name = "test")
public interface FeignAPI {

@RequestMapping(value = "hello")
String hello();

}

Testing

Create a Ribbon Configuration

Create a ribbon configuration to return a list of servers. In our case since we are running tests on local machine, we will return instances of localhost listening on the random port assigned by SpringBootTest web environment.

@Configuration
static class RibbonConfig {

@LocalServerPort
int port;

@Bean
public ServerList<Server> serverList() {
return new StaticServerList<>(new Server("127.0.0.1", port), new Server("127.0.0.1", port));
}
}

Create a Feign Configuration

This configuration will use the Ribbon configuration defined previously to fetch the list of servers where the mock service would be listening. It also creates a rest endpoint for the feign client to hit. This rest endpoint should have the same semantics as the business rest end point (that we are testing using feign client).

EnableFeignClients annotation ensures that spring boot creates a bean for FeignAPI and injects it into the context.

@EnableFeignClients(clients = FeignAPI.class)
@RestController
@Configuration
@EnableAutoConfiguration
@RibbonClient(name = "test", configuration = FeignAPITest.RibbonConfig.class)
static class FeignConfig {

@RequestMapping(value = "hello")
public String testFeign() {
return "success";
}

}

Create the test

Finally, create the test. This has to be a spring boot test. This test will enable the Feign configuration defined above and bring up the environment on a random port. This random port is used by the Ribbon configuration to create mock servers for hosting the mock service.

@SpringBootTest(classes = FeignAPITest.FeignConfig.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class FeignAPITest {

@Autowired
FeignAPI feignAPI;


@Test
public void testFeign() {
assertThat(this.feignAPI.hello()).isEqualTo("success");
}

This way the Feign client is tested in isolation environment calling the server based on the name parameter.

--

--