Reputation: 43
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
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)
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