Bhavin Zalavadia
Bhavin Zalavadia

Reputation: 43

How to mock webclient call to unit test in helidon mp project

Is there a way to mock a web client call from service to unit test it? Example call: Below fragment is for calling consul service from helidon application using webclient. It can be any kind of webclient call to external service.

WebClientResponse webClientResponse = webClient.put().path(sessionRenewPath).submit().get();

I am expecting to mock this webclient call and get webClientResponse. Also how to build a mock webClientResponse?

I am trying something along this lines, but failed

`

@Mock
WebClientRequestBuilder webClientRequestBuilder;
@Mock
Single<WebClientResponse> webClientResponseSingle;
@Mock
WebClientResponse webClientResponse;

Mockito.when(webClient.post()).thenReturn(webClientRequestBuilder);
        Mockito.doReturn(webClientRequestBuilder).when(webClientRequestBuilder).path(Mockito.any(String.class));
        Mockito.doReturn(webClientResponseSingle).when(webClientRequestBuilder).submit();
        Mockito.doReturn(webClientResponse).when(webClientResponseSingle).get();

`

Upvotes: 3

Views: 357

Answers (1)

Ashwin Prabhu
Ashwin Prabhu

Reputation: 7634

While you could use Mockito for mocking the 3rd party service responses, a better solution would be to simulate the 3rd party API at the HTTP layer using specialized libraries like Hoverfly. The single biggest advantage with Hoverfly, when compared to Mockito, is that your code will not be littered with all the mock implementations that can be flaky and difficult to maintain long-term to match the changes in the 3rd party API.

You may think of Hoverfly as a caching proxy layer between your service and the 3rd party. The proxy can either let the traffic pass through to the destination if you want it to or shortcircuit the outbound calls by serving saved responses from its internal cache (which is the default behavior and how it is supposed to be used). Your webclient or http-client code will never know the difference and will always work like it is talking over the network. You don't need any additional infra setup beyond a test-scoped maven dependency in your project to make all of this work.

Additional benefits you will get are(which Mockito can never match)

  1. Replace slow, flaky API dependencies with realistic, re-usable simulations.
  2. Simulate network latency, random failures or rate limits to test edge-cases.
  3. Simulate API responses for outbound calls from the unitest code as well as the outbound calls originating from within the application under test seamlessly (responses to all outbound calls from the JVM on an observed port can be simulated without distinction).
  4. Export, share, edit, and import API simulations
  5. Capture API responses via CLI or code and checkin the responses as golden reference for CI pipeline automation.
  6. Match changes to the 3rd party API response by recapturing the response and updating golden reference in your repository, without changing any test automation code.

You can add hoverfly support to your JUnit test classes declaratively through annotations, like below:

    @HelidonTest // HelidonTest is Optional if you want CDI in tests!
    @HoverflySimulate(
        source = @HoverflySimulate.Source(value = "<path-to-hoverfly-saved-api-response>.json", type = HoverflySimulate.SourceType.DEFAULT_PATH),
        config = @HoverflyConfig(proxyLocalHost = true, proxyPort = <API-PORT>, webServer = true, disableTlsVerification = true)
    )
    @ExtendWith(HoverflyExtension.class)
    class TestRemoteServiceWithHoverfly 
    {
        @Test
        public void testWebClientToRemoteService()
        { 
           Response remoteResponse = 
 _target.path(<API_PATH>).request().get()
        }

        @Inject
        private WebTarget _target;
    }

Upvotes: 1

Related Questions