javanetflix-eurekaspring-cloud-netflixwiremockfeign

How to Integration Test spring-cloud-netflix & Feign, using WireMock


I use Spring-Cloud-Netflix for communication between micro services. Let's say I have two services, Foo and Bar, and Foo consumes one of Bar's REST endpoints. I use an interface annotated with @FeignClient:

@FeignClient
public interface BarClient {
  @RequestMapping(value = "/some/url", method = "POST")
  void bazzle(@RequestBody BazzleRequest);
}

Then I have a service class SomeService in Foo, which calls the BarClient.

@Component
public class SomeService {
    @Autowired
    BarClient barClient;

    public String doSomething() {
      try {
        barClient.bazzle(new BazzleRequest(...));
        return "so bazzle my eyes dazzle";
      } catch(FeignException e) {
        return "Not bazzle today!";
      }

    }
}

Now, to make sure the communication between services works, I want to build a test that fires a real HTTP request against a fake Bar server, using WireMock. The test should make sure that feign correctly decodes the service response and reports it to SomeService.

public class SomeServiceIntegrationTest {

    @Autowired SomeService someService;

    @Test
    public void shouldSucceed() {
      stubFor(get(urlEqualTo("/some/url"))
        .willReturn(aResponse()
            .withStatus(204);

      String result = someService.doSomething();

      assertThat(result, is("so bazzle my eyes dazzle"));
    }

    @Test
    public void shouldFail() {
      stubFor(get(urlEqualTo("/some/url"))
        .willReturn(aResponse()
            .withStatus(404);

      String result = someService.doSomething();

      assertThat(result, is("Not bazzle today!"));
    }
}

How can I successfully inject such a WireMock server into Eureka, so that Feign is able to find it and communicate with it?


Solution

  • Use Spring's RestTemplate instead of feign. RestTemplate is also able to resolve service names via eureka, so you can do something like this:

    @Component
    public class SomeService {
       @Autowired
       RestTemplate restTemplate;
    
       public String doSomething() {
         try {
           restTemplate.postForEntity("http://my-service/some/url", 
                                      new BazzleRequest(...), 
                                      Void.class);
           return "so bazzle my eyes dazzle";
         } catch(HttpStatusCodeException e) {
           return "Not bazzle today!";
         }
       }
    }
    

    This is way easier testable with Wiremock than feign.