0

I have two microservices Microservice A ( context path - /abc ) and microservice B (context path - /def )

Example URLs: test.domain.com/abc/endpoint1 ,test.domain.com/def/endpoint2

In one of the apis of Microservice A ( test.domain.com/abc/endpoint1) internally its making call to Microservice B (/def/endpoint2) -> the prefix for this internal call is generated as follows (Extract the domain from the request and then append /def/endpoint2 to make a rest call the total url will become as (test.domain.com/def/endpoint2)

Problem : When we are writting unit test cases starting controller level we are using TestRestTemplate For this testing we need to use http://localhost:portnumber/abc/endpoint1 to test ..

Now the url of the def service also will be derived as http://localhost:portnumber/def/endpoint2 How to mock this response ( Note: We cannot use mock server on same port, we will get port binding exception) . Is there any workaround for the same?

Is there any way to have gateway kind of setup while using TestRestTemplate to route http://localhost:portnumber/def/* calls to get response from mockserver and http://localhost:portnumber/abc/* to make the actual API Service under test?

svs teja
  • 957
  • 2
  • 22
  • 43

1 Answers1

1

You could use a ClientHttpRequestInterceptor for this and manipulate the actual URI to call if it matches the path of your second microservice.

This might be a naive protoypish implementation:

public class UrlRewriter implements ClientHttpRequestInterceptor {
  @Override
  public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
    try {
      if (httpRequest.getURI().toString().contains("/def/abc")) {
        HttpRequest modifiedRequest = new MockClientHttpRequest(HttpMethod.GET, new URI("http://localhost:8888/def/abc"));
        return clientHttpRequestExecution.execute(modifiedRequest, bytes);
      } else {
        return clientHttpRequestExecution.execute(httpRequest, bytes);
      }

    } catch (URISyntaxException e) {
      e.printStackTrace();
      return null;
    }
  }
}

And then you can provide a custom bean of type RestTemplateBuilder for your test that is picked up by the TestRestTemplate:

@SpringBootTest(webEnvironment = RANDOM_PORT)
public class TestOne {


  @TestConfiguration
  static class TestConfig {

    @Bean
    public RestTemplateBuilder restTemplateBuilder() {
      return new RestTemplateBuilder().interceptors(new UrlRewriter());
    }

  }

  @Autowired
  private TestRestTemplate testRestTemplate;

  @Test
  public void test() {
    assertNotNull(testRestTemplate);

    testRestTemplate.getForObject("/abc/endpoint1", String.class);
  }
}
rieckpil
  • 10,470
  • 3
  • 32
  • 56
  • I have a similar issue but I cannot solve it. Can you help me ? Here is the link : https://stackoverflow.com/questions/74737014/spring-boot-microservice-junit-controller-test-cannot-call-another-service-m – S.N Dec 09 '22 at 20:01