Search code examples
javaspringspring-bootnetflix-eurekawiremock

Spring Boot Integration Test with WireMock and Eureka fails with "No instances available"


When writing an integration test for a Spring Boot application (Service A) that uses a RestTemplate (and Ribbon under the hood) and Eureka to resolve a Service B dependency, I get a "No instances available" exception when calling the Service A.

I try to mock the Service B away via WireMock, but I don't even get to the WireMock server. It seems like the RestTemplate tries to fetch the Service instance from Eureka, which doesn't run in my test. It is disabled via properties.

Service A calls Service B. Service discovery is done via RestTemplate, Ribbon and Eureka.

Does anyone have a working example that includes Spring, Eureka and WireMock?


Solution

  • I faced the same problem yesterday and for the sake of completeness here is my solution:

    This is my "live" configuration under src/main/java/.../config:

    //the regular configuration not active with test profile
    @Configuration
    @Profile("!test")
    public class WebConfig {
        @LoadBalanced
        @Bean
        RestTemplate restTemplate() {
            //you can use your regular rest template here.
            //This one adds a X-TRACE-ID header from the MDC to the call.
            return TraceableRestTemplate.create();
        }
    }
    

    I added this configuration to the test folder src/main/test/java/.../config:

    //the test configuration
    @Configuration
    @Profile("test")
    public class WebConfig {
        @Bean
        RestTemplate restTemplate() {
            return TraceableRestTemplate.create();
        }
    }
    

    In the test case, I activated profile test:

     //...
    @ActiveProfiles("test")
    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class ServerCallTest {
       @Autowired
       private IBusiness biz;
    
       @Autowired
       private RestTemplate restTemplate;
    
       private ClientHttpRequestFactory originalClientHttpRequestFactory;
    
       @Before
       public void setUp() {
           originalClientHttpRequestFactory = restTemplate.getRequestFactory();
       }
    
       @After
       public void tearDown() {
          restTemplate.setRequestFactory(originalClientHttpRequestFactory);
       }
    
       @Test
       public void fetchAllEntries() throws BookListException {
          MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
    
           mockServer                
                .andExpect(method(HttpMethod.GET))
                .andExpect(header("Accept", "application/json"))
                .andExpect(requestTo(endsWith("/list/entries/")))
                .andRespond(withSuccess("your-payload-here", MediaType.APPLICATION_JSON));
    
           MyData data = biz.getData();
    
           //do your asserts
       }
    }