Suffered a lot in finding how to mock http response . Mocking http request for the same library was easy . Thought to create a thread here , to save your time should you need it .
Requirement ->
Wanted to mock a HttpResponse that is returned when any HttpRequest object is executed . (Note - this is specifically for google client api library)
//creating mockContent for httpRequest
MockHttpContent mockHttpContent = new MockHttpContent();
String content = new String("requestBody");
mockHttpContent.setContent(str.getBytes());
//mocking httpResponse and linking to httpRequest's execution
HttpTransport transport =
new MockHttpTransport() {
#Override
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
return new MockLowLevelHttpRequest() {
#Override
public LowLevelHttpResponse execute() throws IOException {
MockLowLevelHttpResponse result = new MockLowLevelHttpResponse();
result.setContent("responseBody");
result.setContentEncoding("UTF-8");//this is very important
result.setHeaderNames(List.of("header1","header2"));
result.setHeaderValues(List.of("header1","header2"));
return result;
}
};
}
};
HttpRequest httpRequest = transport.createRequestFactory().buildPostRequest(HttpTesting.SIMPLE_GENERIC_URL,mockHttpContent);
//getting httpResponse from httpRequest
httpResponse = httpRequest.execute();
//condition to verify the content (body) of the response
assertEquals("responseBody",IOUtils.toString(httpResponse.getContent()));
I am using MockRestServiceServer for unit testing my rest end point. I have one unit test in working condition when I use
mockServer.expect(requestTo(containsString(ROOT_RESOURCE_PATH))).andExpect(method(HttpMethod.POST))
.andRespond(withSuccess(response, MediaType.TEXT_PLAIN));
But same fails when I use
mockServer.expect(requestTo(containsString(ROOT_RESOURCE_PATH))).andExpect(method(HttpMethod.POST))
.andRespond(withBadRequest().body("test").contentType( MediaType.TEXT_PLAIN));
Here is complete code
#Test
public void testPost() {
ClientHttpRequestFactory originalRequestFactory = restTemplate.getRequestFactory();
mockServer = MockRestServiceServer.createServer(restTemplate);
try {
WebTarget target = getRootTarget("/test").path("");
String payLoad = ReadFile("src/test/resources/SamplePayload.html");
String response = ReadFile("src/test/resources/SampleResponse.txt");
Assert.assertNotNull(payLoad);
Assert.assertNotNull(response);
final javax.ws.rs.client.Entity<String> entity = javax.ws.rs.client.Entity.entity(payLoad, "text/plain");
mockServer.expect(requestTo(containsString(ROOT_RESOURCE_PATH))).andExpect(method(HttpMethod.POST))
.andRespond(withSuccess(response, MediaType.TEXT_PLAIN));
final Response mockResponse = target.request().post(entity);
mockServer.verify();
Assert.assertNotNull("Response must not be null", mockResponse.getEntity());
Assert.assertEquals("Response does not have expected response code", 200, mockResponse.getStatus());
} finally {
restTemplate.setRequestFactory(originalRequestFactory);
}
}
#Test
public void testPostWithEmptyBody() {
ClientHttpRequestFactory originalRequestFactory = restTemplate.getRequestFactory();
mockServer = MockRestServiceServer.createServer(restTemplate);
try{
WebTarget target = getRootTarget("/test").path("");
String entityBody = new String();
final javax.ws.rs.client.Entity<String> entity = javax.ws.rs.client.Entity.entity(entityBody, "text/plain");
mockServer.expect(requestTo(containsString(ROOT_RESOURCE_PATH))).andExpect(method(HttpMethod.POST))
.andRespond(withBadRequest().body("test").contentType( MediaType.TEXT_PLAIN));
final Response response = target.request().post(entity);
mockServer.verify();
Assert.assertNotNull("Response must not be null", response.getEntity());
Assert.assertEquals("Response does not have expected response code", 400, response.getStatus());
}finally {
restTemplate.setRequestFactory(originalRequestFactory);
}
}
target.request().post() is funciton which just calls
resttemplate.postForEntity
In second test case I am expecting a status code of 400 but instead I am getting 500 .Any suggestions?
Maybe your RestTemplate not contains right MessageConvertor for resolving
MediaType.TEXT_PLAIN.
I am not sure why PowerMockito.when returns null. This is my class under test:
public class A {
public Integer callMethod(){
return someMethod();
}
private Integer someMethod(){
//Some Code
HttpPost httpPost = new HttpPost(oAuthMessage.URL);
//Some Code
HttpClient httpClient = HttpClientBuilder.create().build();
HttpResponse httpResponse = httpClient.execute(httpPost); ------1
Integer code = httpResponse.getStatusLine().getStatusCode(); ---2
return code;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({ MacmillanServiceImpl.class, PersonService.class, AuthorizeServiceImpl.class, ProvisionHelper.class, ESPHelper.class,
DPFServiceImpl.class, TransactionLogServiceImpl.class, HttpClient.class, HttpEntity.class, InputStream.class, IOUtils.class,
DTOUtils.class, MacmillanESPResponseDTO.class, HttpClientBuilder.class, CloseableHttpClient.class, HttpPost.class, IOUtils.class,
HttpResponse.class, CloseableHttpResponse.class, StatusLine.class })
#PowerMockIgnore({ "javax.crypto.*", "javax.net.ssl.*" })
public class TestA {
//Spying some things here & Injecting them
#Test
public void testA() {
HttpClient httpClientMock = PowerMockito.mock(HttpClient.class);
HttpClientBuilder httpClientBuilderMock = PowerMockito.mock(HttpClientBuilder.class);
CloseableHttpClient closeableHttpClientMock = PowerMockito.mock(CloseableHttpClient.class);
HttpResponse httpResponseMock = PowerMockito.mock(HttpResponse.class);
PowerMockito.mockStatic(HttpClientBuilder.class);
given(HttpClientBuilder.create()).willReturn(httpClientBuilderMock);
when(httpClientBuilderMock.build()).thenReturn(closeableHttpClientMock);
PowerMockito.when(httpClientMock.execute(httpPost)).thenReturn(httpResponseMock); --This does not work----Line 3
//Other codes
//call the method
}
In line-1 I get httpResponse as null. I want to get a mocked HTTPResponse object so that I can proceed further.
I have also tried this instead of Line 3:
CloseableHttpResponse closeableHttpResponse = PowerMockito.mock(CloseableHttpResponse.class);
PowerMockito.when(closeableHttpClientMock.execute(httpPost)).thenReturn(closeableHttpResponse);
Can anyone help me?
Seems that the issue is that the httpPost instance that you pass when mocking is not the same as the one you pass in the execution.
What you can do to resolve this is use Matchers.eq() when you mock, that way the when will be executed on every object equals to the one you pass:
PowerMockito.when(httpClientMock.execute(Matchers.eq(httpPost)))
.thenReturn(httpResponseMock);
I am writing a Junit test with apache httpclient. The testCreate method successfully insert a record to the database but the status return is 500 which make the test case to fail.
Below is the test case,
public void testCreate() throws Exception {
String url = "http://localhost:8080/mediaactivity/videoAssignment";
HttpPost request = new HttpPost(url);
request.addHeader("Content-Type", "application/json");
request.addHeader("xAuthorization", "123");
request.addHeader("correlationId", "123");
String json = "{"+
"\"VideoType\": \"Sample\","+
"\"groupType\": \"INDIVIDUAL\","+
"\"submissionMethod\": \"test\","+
"\"title\": \"test me\""+
"}";
StringEntity entity = new StringEntity(json);
request.setEntity(entity);
// When
HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);
// Then
assertThat(httpResponse.getStatusLine().getStatusCode(), equalTo(HttpStatus.SC_CREATED));
}
The controller looks like,
#RequestMapping(value = "/videoAssignment", produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE, method = RequestMethod.POST)
#ResponseBody
public HttpEntity<VideoAssignment> createVideoAssingnment(
//#ApiParam are there..){
//other methods
return new ResponseEntity<>(va, HttpStatus.CREATED);
}
what i am missing here?
I have written a REST web service in Netbean IDE using Jersey Framework and Java.
For every request the user needs to provide a username and a password, I know that this authentication is not a best practice (using a curl command like: curl -u username:password -X PUT http://localhsot:8080/user).
Now I want to call a REST web service from an Android Class.
How should I do it?
I have an Android Class which uses DefaultHttpClient and CredentialUsernameAndPassword, but when I run it in Eclipse, sometimes I get a runtime exception or SDK exception.
This is an sample restclient class
public class RestClient
{
public enum RequestMethod
{
GET,
POST
}
public int responseCode=0;
public String message;
public String response;
public void Execute(RequestMethod method,String url,ArrayList<NameValuePair> headers,ArrayList<NameValuePair> params) throws Exception
{
switch (method)
{
case GET:
{
// add parameters
String combinedParams = "";
if (params!=null)
{
combinedParams += "?";
for (NameValuePair p : params)
{
String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue(),"UTF-8");
if (combinedParams.length() > 1)
combinedParams += "&" + paramString;
else
combinedParams += paramString;
}
}
HttpGet request = new HttpGet(url + combinedParams);
// add headers
if (headers!=null)
{
headers=addCommonHeaderField(headers);
for (NameValuePair h : headers)
request.addHeader(h.getName(), h.getValue());
}
executeRequest(request, url);
break;
}
case POST:
{
HttpPost request = new HttpPost(url);
// add headers
if (headers!=null)
{
headers=addCommonHeaderField(headers);
for (NameValuePair h : headers)
request.addHeader(h.getName(), h.getValue());
}
if (params!=null)
request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
executeRequest(request, url);
break;
}
}
}
private ArrayList<NameValuePair> addCommonHeaderField(ArrayList<NameValuePair> _header)
{
_header.add(new BasicNameValuePair("Content-Type","application/x-www-form-urlencoded"));
return _header;
}
private void executeRequest(HttpUriRequest request, String url)
{
HttpClient client = new DefaultHttpClient();
HttpResponse httpResponse;
try
{
httpResponse = client.execute(request);
responseCode = httpResponse.getStatusLine().getStatusCode();
message = httpResponse.getStatusLine().getReasonPhrase();
HttpEntity entity = httpResponse.getEntity();
if (entity != null)
{
InputStream instream = entity.getContent();
response = convertStreamToString(instream);
instream.close();
}
}
catch (Exception e)
{ }
}
private static String convertStreamToString(InputStream is)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try
{
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
is.close();
}
catch (IOException e)
{ }
return sb.toString();
}
}
Recently discovered that a third party library - Square Retrofit can do the job very well.
Defining REST endpoint
public interface GitHubService {
#GET("/users/{user}/repos")
List<Repo> listRepos(#Path("user") String user,Callback<List<User>> cb);
}
Getting the concrete service
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.build();
GitHubService service = restAdapter.create(GitHubService.class);
Calling the REST endpoint
List<Repo> repos = service.listRepos("octocat",new Callback<List<User>>() {
#Override
public void failure(final RetrofitError error) {
android.util.Log.i("example", "Error, body: " + error.getBody().toString());
}
#Override
public void success(List<User> users, Response response) {
// Do something with the List of Users object returned
// you may populate your adapter here
}
});
The library handles the json serialization and deserailization for you. You may customize the serialization and deserialization too.
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.registerTypeAdapter(Date.class, new DateTypeAdapter())
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.setConverter(new GsonConverter(gson))
.build();
Stop with whatever you were doing ! :)
Implement the RESTful client as a SERVICE and delegate the intensive network stuff to activity independent component: a SERVICE.
Watch this insightful video
http://www.youtube.com/watch?v=xHXn3Kg2IQE where Virgil Dobjanschi is explaining his approach(es) to this challenge...
Using Spring for Android with RestTemplate
https://spring.io/guides/gs/consuming-rest-android/
// The connection URL
String url = "https://ajax.googleapis.com/ajax/" +
"services/search/web?v=1.0&q={query}";
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
// Add the String message converter
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
// Make the HTTP GET request, marshaling the response to a String
String result = restTemplate.getForObject(url, String.class, "Android");
I used OkHttpClient to call restful web service. It's very simple.
OkHttpClient httpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response = httpClient.newCall(request).execute();
String body = response.body().string()
What back-end? If JAVA then you can use REST with Java (JAX-RS) using Jersey.
On the Android side you can use this simple RestClient to work with that REST service.
For JSON <--> Object mapping on both sides (Android, Java back-end) you can use GSON.
Perhaps am late or maybe you've already used it before but there is another one called ksoap and its pretty amazing.. It also includes timeouts and can parse any SOAP based webservice efficiently. I also made a few changes to suit my parsing.. Look it up
Follow the below steps to consume RestFul in android.
Step1
Create a android blank project.
Step2
Need internet access permission. write the below code in AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
Step3
Need RestFul url which is running in another server or same machine.
Step4
Make a RestFul Client which will extends AsyncTask. See RestFulPost.java.
Step5
Make DTO class for RestFull Request and Response.
RestFulPost.java
package javaant.com.consuming_restful.restclient;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import com.google.gson.Gson;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import java.util.Map;
import javaant.com.consuming_restful.util.Util;
/**
* Created by Nirmal Dhara on 29-10-2015.
*/
public class RestFulPost extends AsyncTask<map, void,="" string=""> {
RestFulResult restFulResult = null;
ProgressDialog Asycdialog;
String msg;
String task;
public RestFulPost(RestFulResult restFulResult, Context context, String msg,String task) {
this.restFulResult = restFulResult;
this.task=task;
this.msg = msg;
Asycdialog = new ProgressDialog(context);
}
#Override
protected String doInBackground(Map... params) {
String responseStr = null;
Object dataMap = null;
HttpPost httpost = new HttpPost(params[0].get("url").toString());
try {
dataMap = (Object) params[0].get("data");
Gson gson = new Gson();
Log.d("data map", "data map------" + gson.toJson(dataMap));
httpost.setEntity(new StringEntity(gson.toJson(dataMap)));
httpost.setHeader("Accept", "application/json");
httpost.setHeader("Content-type", "application/json");
DefaultHttpClient httpclient= Util.getClient();
HttpResponse response = httpclient.execute(httpost);
int statusCode = response.getStatusLine().getStatusCode();
Log.d("resonse code", "----------------" + statusCode);
if (statusCode == 200)
responseStr = EntityUtils.toString(response.getEntity());
if (statusCode == 404) {
responseStr = "{\n" +
"\"status\":\"fail\",\n" +
" \"data\":{\n" +
"\"ValidUser\":\"Service not available\",\n" +
"\"code\":\"404\"\n" +
"}\n" +
"}";
}
} catch (Exception e) {
e.printStackTrace();
}
return responseStr;
}
#Override
protected void onPreExecute() {
Asycdialog.setMessage(msg);
//show dialog
Asycdialog.show();
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
Asycdialog.dismiss();
restFulResult.onResfulResponse(s,task);
}
}
For more details and complete code please visit http://javaant.com/consume-a-restful-webservice-in-android/#.VwzbipN96Hs
Here is my Library That I have created for simple Webservice Calling,
You can use this by adding a one line gradle dependency -
compile 'com.scantity.ScHttpLibrary:ScHttpLibrary:1.0.0'
Here is the demonstration of using.
https://github.com/vishalchhodwani1992/httpLibrary