I have a service I am mocking like this:
@ExtendWith(MockitoExtension.class) class MyServiceTest { @InjectMocks MyService myService; @Test void testSendRec() { myService.sendDocRec(.. pass params..); }
}
the service:
@Service public class MyService { String sendDocRec( params ) { // builds request HttpUriRequestBase request = getRequest( params ); String response = doRequest(request); } public String doRequest(ClassicHttpRequest request) { String result = null; try (CloseableHttpClient httpclient = HttpClients.custom() .setConnectionManager(this.connectionManager) .setConnectionManagerShared(true) .setDefaultRequestConfig(this.requestConfig) .build()) { final HttpClientContext clientContext = HttpClientContext.create(); try (CloseableHttpResponse response = httpclient.execute(request, clientContext)) { result = EntityUtils.toString(response.getEntity()); } } catch (URISyntaxException e) { log.error("Invalid URI {}", e); } catch (IOException e) { log.error("Failed to make HTTP Request {}", e); } catch (ParseException e) { log.error("Failed parsing response body {}", e); } return result; } }
I need to be able to mock the “CloseableHttpResponse response = httpclient.execute(request, clientContext)”, such that the “response” object is something I create ahead of time. I am hoping some mocking when/then constructs would work for this? I would grateful for ideas on how to do this. Thanks!
Advertisement
Answer
You can’t do it using the current code structure. httpclient object is getting created within the method under test. So it can’t be mocked.
You need to delegate httpclient object creation to another method with belongs to a different class (something similar to HttpClientFactory class). That HttpClientFactory class should only be responsible for creating httpClient instances. If you need you can write separate unit test case for the class.
@Inject private HttpClientFactory httpClientFactory; public String doRequest(ClassicHttpRequest request) { String result = null; try (CloseableHttpClient httpclient = httpClientFactory.getInstance()) { final HttpClientContext clientContext = HttpClientContext.create(); try (CloseableHttpResponse response = httpclient.execute(request, clientContext)) { result = EntityUtils.toString(response.getEntity()); } } catch (URISyntaxException e) { log.error("Invalid URI {}", e); } catch (IOException e) { log.error("Failed to make HTTP Request {}", e); } catch (ParseException e) { log.error("Failed parsing response body {}", e); } return result; }
Now you can mock response like below:
@Mock private HttpClientFactory httpClientFactory; public String testDoRequest(ClassicHttpRequest request) { .... CloseableHttpClient mockedClient = mock(CloseableHttpClient.class); CloseableHttpResponse mockedResponse = mock(CloseableHttpResponse.class); when(httpClientFactory.getInstance()).thenReturn(mockedClient); when(mockedClient.execute(eq(request), any(clientContext))).thenReturn(mockedResponse); ....}