I have no idea before how to write the test cases, when i saw online tutorials i understand how to write it for a simple method with success and failure scenario. Now i have a method for http get which calls a restful API and returns a json response. I have like 6 parameters to include in the url and get a json response back. Now, my understanding so far is for success scenario here i should just hard code those input parameters and test if i am getting json back and for failure not getting json response back. Is this correct or do i have to do something else?
i mean i have a code something like
public List getStoreLocations(StoreData storeData) {
List storeList = null;
try {
HttpClient httpclient = HttpClientBuilder.create().build();
StringBuilder urlStrngBuildr = new StringBuilder(
https://<hostname>/xyz/abc);
Utility.addParameterToUrl(urlStrngBuildr,
Utility.APP_NAME,
Constants.APP_VALUE);
Utility.addParameterToUrl(urlStrngBuildr,
Constants.VERSION_PARAM_NAME,
Constants.VERSION_PARAM_VALUE);
if (storeData.getCity() != null && storeData.getState() != null) {
StringBuilder addressParamValue = new StringBuilder(
storeData.getCity());
addressParamValue.append(Constants.COMMA);
addressParamValue.append(storeData.getState());
Utility.addParameterToUrl(urlStrngBuildr,
Constants.ADDRESS_PARAM_NAME,
addressParamValue.toString());
} else if (storeData.getZip() != null) {
Utility.addParameterToUrl(urlStrngBuildr,
Constants.ZIP_PARAM_NAME, storeData.getZip());
}
Utility.addParameterToUrl(urlStrngBuildr,
Constants.PRODUCT_PARAM_NAME,
storeData.getProduct());
Utility.addParameterToUrl(urlStrngBuildr,
Constants.COUNTRY_PARAM_NAME,
storeData.getCountry());
Utility.addParameterToUrl(urlStrngBuildr,
Constants.DISTANCE_PARAM_NAME,
storeData.getDistance());
Utility.addParameterToUrl(urlStrngBuildr,
Constants.SIZE_PARAM_NAME, storeData.getSize());
HttpGet getRequest = new HttpGet(new java.net.URI(
urlStrngBuildr.toString()));
getRequest.addHeader(BasicScheme.authenticate(
new UsernamePasswordCredentials(username,password),
Constants.ENCODING_TYPE, false));
JSONResponseHandler responseHandler = new JSONResponseHandler();
String json = httpclient.execute(getRequest, responseHandler)
.toString();
Gson gson = new Gson();
StoreResponse response = gson.fromJson(json,
StoreResponse.class);
StoreDetails[] strDetails = response.getResult();
storeDetailsList = Arrays.asList(strDetails);
} catch (Exception exeption) {
exeption.printStackTrace();
}
return storeList;
}
Maybe you should take a look at REST-assured, which is a REST API testing framework.
The nice thing is, that it is much easier to read, supports JSON and XML and allows you to test things like HTTP-Codes or specific values from the response.
get("/lotto")
.then()
.assertThat().body("lotto.lottoId", equalTo(5));
You could add your parameters with the param method:
given()
.param("key1", "value1")
.param("key2", "value2")
when().
aso...
If you need authentication, like in your code, you can just use something like the following:
given()
.auth()
.basic(username,password)
.when()
.get("/secured")
.then()
.statusCode(200);`
Hope this helps with your testing.
It looks like the main thign you need to mock on that method is the HTtpClient. So how about you create a method for getting the client, then mock that method so that it returns a mock HttpClient.
public HttpClient getHttpClient(){
return HttpClientBuilder.create().build();
}
Then in your method you will do:
HttpClient httpclient = getHttpClient();
Then in your unit test code you will mock the getHttpClient method like so..
HttpClient mockClient = mock(HttpClient.class);
MyClassBeingTested instance = spy(new MyClassBeingTested ());
when(instance .getHttpClient()).thenReturn(mockClient);
when(mockClient.execute(any(HttpGet.class),any(JSONResponseHandler.class)).thenReturn(testJsonString);
List actual = instance.getStoreLocations(storeData);
Something like that.
Related
I'm trying to do a network request with HttpURLConnection and JSONObject, like this.
Step 1: class to serialize the request object
fun <T> GsonBuilder.getEncryptedJSON(request: T): JSONObject {
var encryptedJSON = JSONObject()
try {
var data = this
.excludeFieldsWithoutExposeAnnotation()
.registerTypeAdapter(String::class.java, StringEncryptSerializer())
.registerTypeAdapter(java.lang.Long::class.java, LongEncryptSerializer())
.disableHtmlEscaping()
.create()
.toJson(request)
encryptedJSON = JSONObject(data)
} catch (exception: JSONException) {
Log.e("exception-json", exception.toString())
}
return encryptedJSON
}
Step 2: Class UploadRequest that extends HttpRequest and has a property called body witch is type of JSONObject
uploadRequest.body = GsonBuilder().getEncryptedJSON<UploadRequest>(this)
Step 3: request after a few steps, is the request HTTP class
postData = request.getBody().toString().getBytes(StandardCharsets.UTF_8);
wr = new DataOutputStream(connection.getOutputStream());
wr.write(postData);
wr.flush();
I've seen: After transform my body into JSONObject, the problem happens.
The result I expected is bellow:
{"fileName":""0NKTqOdZ154T/ksxOwdx0VzHNQmGfM0UlpPrreb0vFnGh/Rw3UZEx94aUAuZtr8lW/da07/h/RNoyXpMqpGXKA===="}
But, everytime I've seen the log inside the gateway, the request content is ESCAPING FOWARD SLASHES, like this
{"fileName":""0NKTqOdZ154T\/ksxOwdx0VzHNQmGfM0UlpPrreb0vFnGh\/Rw3UZEx94aUAuZtr8lW\/da07\/h\/RNoyXpMqpGXKA===="}
Do you have any idea why this happen?!
Thank you!
I would like to test an application that connects to Github api, download some records and do something with them.
I want to have a mock object and I did something like that:
#SpringBootTest
public class GithubApiTest
{
GithubApiClient githubApiClient;
#Mock
HttpClient httpClient;
HttpRequest httpRequest;
#Value("response.json")
private String response;
#BeforeTestClass
void init() throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create("https://api.github.com/repos/owner/reponame"))
.build();
githubApiClient = new GithubApiClient(httpClient);
Mockito.when(httpClient.send(request, HttpResponse.BodyHandlers.ofString())).thenReturn(<here>
);
githubApiClient = new GithubApiClient(httpClient);
}
}
Looks it good? What should I put into thenReturn (it needs a HttpResponse but I dont know how to create this). Thanks for your answers. If you have any better ideas I will be grateful.
Update:
String response is a example reponse
You create a mocked response of type HttpResponse.
The mockedResponse will have status code 200, and the response body is "ExampleOfAResponseBody" which is of type String which you requested.
import java.net.http.HttpResponse;
HttpResponse<String> mockedResponse = Mockito.mock(HttpResponse.class);
Mockito.when(mockedResponse.statusCode()).thenReturn(200);
Mockito.when(mockedResponse.body()).thenReturn("ExampleOfAResponseBody");
Mockito.when(httpClient.send(request, HttpResponse.BodyHandlers.ofString())).thenReturn(mockedResponse);
I am trying to connect to an API of another company.
from the doc there is ::
even with your GET request, you'll need to include the Java equivalent of
curl_setopt($ch, CURLOPT_POSTFIELDS, $content), and you can set $data equal
to an empty array.
$content in their example is an empty JSON array.
I am using org.apache.commons.httpclient.
i am not sure how to add post fields to a org.apache.commons.httpclient.methods.GetMethod or if it is even possible.
i tried faking with a Content-Length of 2 but the GET times out (probably looking for content that i am not providing. if i remove the content-length i get an invalid response from the api server)
HttpClient client = new HttpClient();
GetMethod method = new GetMethod("https://api.xxx.com/account/");
method.addRequestHeader("Content-Type", "application/json");
method.addRequestHeader("X-Public-Key", APKey);
method.addRequestHeader("X-Signed-Request-Hash", "xxx");
method.addRequestHeader("Content-Length", "2");
int statusCode = client.executeMethod(method);
I don't think GetMethod includes any means of attaching a request body, because a GET request isn't supposed to have a body. (But having a body isn't actually prohibited, either - see: HTTP GET with request body .)
You're trying to use documentation written with a different language and a different client library in mind, so you'll have to use trial and error a bit. It sounds like they expect a request with no body, and you already have that. There's no good reason why they'd require a "Content-Length" with GET, but if that's the case, try setting it to 0.
This is how i resolved this issue
Created this class
public class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {
public HttpGetWithEntity() {
super();
}
public HttpGetWithEntity(URI uri) {
super();
setURI(uri);
}
public HttpGetWithEntity(String uri) {
super();
setURI(URI.create(uri));
}
#Override
public String getMethod() {
return HttpGet.METHOD_NAME;
}
}
Then the calling function looks like
public JSONObject get(JSONObject payload, String URL) throws Exception {
JSONArray jsonArray = new JSONArray();
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpGetWithEntity myGet = new HttpGetWithEntity(WeeblyAPIHost+URL);
myGet.setEntity( new StringEntity("[]") );
myGet.setHeader("Content-Type", "application/json");
myGet.setHeader("X-Public-Key", APIKey);
HttpResponse response = client.execute(myGet);
JSONParser parser = new JSONParser();
Object obj = parser.parse( EntityUtils.toString(response.getEntity(), "UTF-8") ) ;
JSONObject jsonResponse = (JSONObject) obj;
return jsonResponse;
}
Is there any way to avoid the return null in this code?
#Test
public void testFrontEndPing() throws Exception {
String url = frontEndUrl("ping");
HttpGet httpGet = new HttpGet(url);
httpClient.execute(httpGet, httpResponse -> {
assertEquals(200, httpResponse.getStatusLine().getStatusCode());
return null;
}
);
}
You can write a wrapper method like this:
static void execute(HttpClient client, HttpUriRequest request,
Consumer<HttpResponse> handler) {
client.<Void>execute(request, response -> {
handler.accept(response);
return null;
});
}
And use it like this:
execute(httpClient, httpGet, httpResponse ->
assertEquals(200, httpResponse.getStatusLine().getStatusCode()));
The Functional Interface you're trying to work with mandates that the function return an object. So no matter how you code this functionality, somewhere you'll have to include 'return null;'
I would advise that you analyze what the code is meant to do, and whether, per the design of your code, you really want that method to always return null.
I am using the latest okhttp version: okhttp-2.3.0.jar
How to add query parameters to GET request in okhttp in java ?
I found a related question about android, but no answer here!
For okhttp3:
private static final OkHttpClient client = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
public static void get(String url, Map<String,String>params, Callback responseCallback) {
HttpUrl.Builder httpBuilder = HttpUrl.parse(url).newBuilder();
if (params != null) {
for(Map.Entry<String, String> param : params.entrySet()) {
httpBuilder.addQueryParameter(param.getKey(),param.getValue());
}
}
Request request = new Request.Builder().url(httpBuilder.build()).build();
client.newCall(request).enqueue(responseCallback);
}
Here's my interceptor
private static class AuthInterceptor implements Interceptor {
private String mApiKey;
public AuthInterceptor(String apiKey) {
mApiKey = apiKey;
}
#Override
public Response intercept(Chain chain) throws IOException {
HttpUrl url = chain.request().url()
.newBuilder()
.addQueryParameter("api_key", mApiKey)
.build();
Request request = chain.request().newBuilder().url(url).build();
return chain.proceed(request);
}
}
I finally did my code, hope the following code can help you guys. I build the URL first using
HttpUrl httpUrl = new HttpUrl.Builder()
Then pass the URL to Request requesthttp hope it helps .
public class NetActions {
OkHttpClient client = new OkHttpClient();
public String getStudentById(String code) throws IOException, NullPointerException {
HttpUrl httpUrl = new HttpUrl.Builder()
.scheme("https")
.host("subdomain.apiweb.com")
.addPathSegment("api")
.addPathSegment("v1")
.addPathSegment("students")
.addPathSegment(code) // <- 8873 code passthru parameter on method
.addQueryParameter("auth_token", "71x23768234hgjwqguygqew")
// Each addPathSegment separated add a / symbol to the final url
// finally my Full URL is:
// https://subdomain.apiweb.com/api/v1/students/8873?auth_token=71x23768234hgjwqguygqew
.build();
System.out.println(httpUrl.toString());
Request requesthttp = new Request.Builder()
.addHeader("accept", "application/json")
.url(httpUrl) // <- Finally put httpUrl in here
.build();
Response response = client.newCall(requesthttp).execute();
return response.body().string();
}
}
As mentioned in the other answer, okhttp v2.4 offers new functionality that does make this possible.
See http://square.github.io/okhttp/2.x/okhttp/com/squareup/okhttp/HttpUrl.Builder.html#addQueryParameter-java.lang.String-java.lang.String-
This is not possible with the current version of okhttp, there is no method provided that will handle this for you.
The next best thing is building an url string or an URL object (found in java.net.URL) with the query included yourself, and pass that to the request builder of okhttp.
As you can see, the Request.Builder can take either a String or an URL.
Examples on how to build an url can be found at What is the idiomatic way to compose a URL or URI in Java?
As of right now (okhttp 2.4), HttpUrl.Builder now has methods addQueryParameter and addEncodedQueryParameter.
You can create a newBuilder from existing HttoUrl and add query parameters there. Sample interceptor code:
Request req = it.request()
return chain.proceed(
req.newBuilder()
.url(
req.url().newBuilder()
.addQueryParameter("v", "5.60")
.build());
.build());
Use HttpUrl class's functions:
//adds the pre-encoded query parameter to this URL's query string
addEncodedQueryParameter(String encodedName, String encodedValue)
//encodes the query parameter using UTF-8 and adds it to this URL's query string
addQueryParameter(String name, String value)
more detailed: https://stackoverflow.com/a/32146909/5247331