I know how to mock a default HttpClient, but how do I mock the latest (v4.4) HttpClient that is created using a PoolingHttpClientConnectionManager with Mockito?
My code looks like this:
PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
...
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(mgr).build();
HttpResponse response = httpClient.execute(request);
... // here I want to substitute a mocked HttpResponse
It is likely to be easier to mock out HttpRequestExecutor than HttpClientConnection. You would still need to provide a no-op implementation of HttpClientConnectionManager in order to prevent HttpClient from creating and connecting sockets
HttpRequestExecutor requestExecutor = Mockito.mock(HttpRequestExecutor.class);
Mockito.when(requestExecutor.execute(
Mockito.<HttpRequest>any(),
Mockito.<HttpClientConnection>any(),
Mockito.<HttpContext>any())).thenReturn(new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "Hah"));
HttpClientConnectionManager cm = Mockito.mock(HttpClientConnectionManager.class);
HttpClientConnection conn = Mockito.mock(HttpClientConnection.class);
ConnectionRequest connRequest = Mockito.mock(ConnectionRequest.class);
Mockito.when(cm.requestConnection(
Mockito.<HttpRoute>any(),
Mockito.any())).thenReturn(connRequest);
Mockito.when(connRequest.get(
Mockito.anyLong(),
Mockito.<TimeUnit>any())).thenReturn(conn);
CloseableHttpClient client = HttpClients.custom()
.setRequestExecutor(requestExecutor)
.setConnectionManager(cm)
.build();
CloseableHttpResponse response = client.execute(new HttpGet("http://pampa/"));
try {
System.out.println(response.getStatusLine());
} finally {
response.close();
}
Just realized that PoolingHttpClientConnectionManager is the default connection manager used by HttpClient built with HttpClients.custom().build() (at least in v4.4), so I just went back to mocking the HttpClient.
protected HttpClient buildHttpClient() {
return HttpClients.custom()./* other config */.build();
}
unit test code:
#Mock
HttpClient mockClient;
#Mock
HttpResponse mockResponse;
#Spy
MyClass myclass = new MyClass();
. . .
#Test
public void myTestCase() {
. . .
when(myclass.buildHttpClient()).thenReturn(mockClient);
when(mockClient.execute(requestCaptor.capture())).thenReturn(mockResponse);
. . .
Related
I am trying to Mock the below code but unsuccessful, Can anyone suggest how this can be achieved.
HttpClient httpClient = HttpClient.create()
.tcpConfiguration(tcpClient -> tcpClient
.proxy(proxy -> proxy
.type(ProxyProvider.Proxy.HTTP)
.host(host)
.port(Integer.parseInt(port))));
ClientHttpConnector clientHttpConnector = new ReactorClientHttpConnector(httpClient);
webClient = WebClient.builder().clientConnector(clientHttpConnector).build();
Move the code which creates the HttpClient to it's own class:
interface HttpClientFactory {
HttpClient create();
}
class DefaultHttpClientFactory implements {
HttpClient create() {
return HttpClient.create()
.tcpConfiguration(tcpClient -> tcpCl...
}
}
Now you can mock HttpClientFactory and the mock HttpClient it returns.
How can I use a custom configured Apache HttpClient with Jersey Client 2?
HttpClient with Caching (from apache docs)
CacheConfig cacheConfig = CacheConfig.custom()
.setMaxCacheEntries(1000)
.setMaxObjectSize(8192)
.build();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(30000)
.setSocketTimeout(30000)
.build();
CloseableHttpClient cachingClient = CachingHttpClients.custom()
.setCacheConfig(cacheConfig)
.setDefaultRequestConfig(requestConfig)
.build();
Using Apache Http in general works by setting
protected ClientConfig getClientConfig() {
ClientConfig config = new ClientConfig();
config.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
config.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
final ApacheConnectorProvider connector = new ApacheConnectorProvider();
config.connectorProvider(connector);
return config;
}
But how to use custom http client config like above?
You can use ApacheHttpClientBuilderConfigurator. So you can do:
config.register(new ApacheHttpClientBuilderConfigurator() {
public HttpClientBuilder configure(HttpClientBuilder httpClientBuilder) {
return httpClientBuilder.setDefaultRequestConfig(requestConfig);
}
});
See the example.
The Apache caching client is not properly supported at the moment. You may return CachingHttpClientBuilder from the method, but the HttpClientBuilder does not have getters to see what is already set, so you need to set everything from scratch.
I am trying to write unit test cases for my HTTP Client and would like to use mockito to mock the responses received from the server.
public HttpResponse postRequest(String uri, String body) throws IOException {
HttpResponse response;
String url = baseUrl + uri;
try (CloseableHttpClient httpClient = HttpClientBuilder.create()
.build()) {
HttpPost post = new HttpPost(url);
post.setEntity(new StringEntity(body));
post.setHeader(AUTHORIZATION_HEADER, authorization);
post.setHeader(CONTENTTYPE_HEADER, APPLICATION_JSON);
post.setHeader(ACCEPT_HEADER, APPLICATION_JSON);
response = httpClient.execute(post);
} catch (IOException e) {
System.out.println("Caught an exception" + e.getMessage().toString());
logger.error("Caught an exception" + e.getMessage().toString());
throw e;
}
return response;
}
My test class is as follows. I am unable to figure out how I should send my response body.
public class HTTPRequestTest extends Mockito {
private String body = "{a:b}";
#Test
public void xyz throws Exception {
HttpClient httpClient = mock(HttpClient.class);
HttpPost httpPost = mock(HttpPost.class);
HttpResponse httpResponse = mock(HttpResponse.class);
StatusLine statusLine = mock(StatusLine.class);
when(httpClient.execute(httpPost)).thenReturn(body);
}
}
Using PowerMockito :
First annotate your test class
#RunWith(PowerMockRunner.class)
#PrepareForTest(HttpClientBuilder.class)
then your test method can be something like:
#Test
public void xyz() throws Exception {
HttpClientBuilder mockClientBuilder = PowerMockito.mock(HttpClientBuilder.class);
CloseableHttpClient mockHttpClient = PowerMockito.mock(CloseableHttpClient.class);
CloseableHttpResponse mockResponse = PowerMockito.mock(CloseableHttpResponse.class);
PowerMockito.mockStatic(HttpClientBuilder.class);
PowerMockito.when(HttpClientBuilder.class, "create").thenReturn(mockClientBuilder);
PowerMockito.when(mockClientBuilder.build()).thenReturn(mockHttpClient);
PowerMockito.when(mockHttpClient.execute(any(HttpPost.class))).thenReturn(mockResponse);
HttpResponse response = classUnderTest.postRequest("uri", "body");
//assertResponse
}
The problem is that your HttpClient mock isn't being used in your unit test.
Your postRequest function creates a new HttpClient using this method:
HttpClientBuilder.create().build()
HttpClientBuilder instantiates a new HttpClient, which is a totally separate instance of HttpClient than the mock you create in your unit test. Unfortunately, there isn't an easy way to test your code as written because Mockito can't mock static methods (like HttpClientBuilder.create). See this post for more discussion of this problem and possible workarounds.
To summarize that post, your options are to either rewrite your code so you can inject a mock more easily, or switch to a mocking framework that can mock static methods (like PowerMock).
As suggested in other answers, PowerMock is definitely an option here to mock static methods (in your case HttpClientBuilder.create().build()), however, for your particular instance, you can also resolve the issue by moving the instantiation of the HttpClient out of your doPost method and declare it as instance variable.
#Mock
CloseableHttpClient httpClient = HttpClientBuilder.create().build()
This way when you mock using Mockito, it will be a mocked object. In JUnit5, this can be done by using #Mock above the CloseableHttpClient declaration and then initializing all mocks in the setup method.
I send http requests over Apache HttpClient and my code is here:
HttpHost proxy = new HttpHost("78.1.1.222", 80);
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
httpClient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.build();
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("Authorization","Basic " + encoding);
httpGet.addHeader("Cache-Control", "no-cache");
httpResponse = httpClient.execute(httpGet);
responseCode=httpResponse.getStatusLine().getStatusCode();
........
........(code continue..)
My question is that how can I add connection timeout time to this code?
Note that I must use proxy with that and I use HttpClient 4.4 .
http://www.baeldung.com/httpclient-timeout explains various ways to set the connection timeout.
I have machine with 4 internet IP's and I want to know if I can make apache http client to make requests from specific ip/network interface
Using HttpClient 4.3 APIs
RequestConfig config = RequestConfig.custom()
.setLocalAddress(InetAddress.getByAddress(new byte[] {127,0,0,1}))
.build();
HttpGet httpGet = new HttpGet("/stuff");
httpGet.setConfig(config);
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
CloseableHttpResponse response = httpClient.execute(httpGet);
try {
// do something useful
} finally {
response.close();
}
} finally {
httpClient.close();
}
Never did this, but there is a ClientConnectionOperator interface (and some factories too) in the API to create the socket. Maybe you can implement your own and create the socket with a concrete interface.