How to test Web Service calls through Junit - java

I would like to test my web service using Junit. Once we missed the public modifier and it failed. So, to avoid such issue in the earlier stage we would like to write Junit test cases to test the web service connection.
I tried this but did not work.
String url = "http://localhost:port/webservice/path";
HttpClient client = new DefaultHttpClient();
HttpUriRequest request = new HttpGet( url );
request.setHeader("username", "user1");
HttpResponse httpResponse =
HttpClientBuilder.create().build().execute(request);
HttpResponse response = client.execute(request);
httpResponse.getStatusLine().getStatusCode();
BufferedReader rd = new BufferedReader(new
InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
while ((line = rd.readLine()) != null) {
result.append(line);
}
My web service will be like this
#Path("/path")
public interface WebServiceTest
{
//list of services
}
I should get to know whether my call is success or failure through Junit test case.
How to implement it? Any other suggestions other than Junit but It should be through Java (No Mockito)?
EDIT: I need this for both SOAP and REST web services.

Try to use RestAssured. Using a method like this and pass the appropriate values.
public static ResponseBody callAPI(String host, String body, String path, String method, Map<String,String> headers){
RequestSpecBuilder requestSpecBuilder = new RequestSpecBuilder();
requestSpecBuilder.addHeaders(headers);
requestSpecBuilder.setBody(body);
requestSpecBuilder.setBaseUri(host);
RequestSpecification requetSpecification = requestSpecBuilder.build();
requestSpecBuilder.setContentType(ContentType.JSON);
Response rs = null;
if(method.equals("DELETE")){
rs = RestAssured.given(requetSpecification).when().log().all().delete(path);
}else if(method.equals("POST")){
rs = RestAssured.given(requetSpecification).when().log().all().post(path);
}
return rs.getBody();
}

Related

Send JSON body in HTTP GET request in java/spring boot

I need to send a GET request with a json body in java/spring boot. I'm aware of the advice against it, however I have to do it this was for a couple of reasons:
1. The 3rd party API I'm using only allows GET requests, so POST is not an option.
2. I need to pass an extremely large parameter in the body (a comma separated list of about 8-10k characters) so tacking query params onto the url is not an option either.
I've tried a few different things:
apache HttpClient from here: Send content body with HTTP GET Request in Java. This gave some error straight from the API itself about a bad key.
URIComponentsBuilder from here: Spring RestTemplate GET with parameters. This just tacked the params onto the url, which as I explained before is not an option.
restTemplate.exchange. This seemed the most straightforward, but the object wouldn't pass: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#exchange-java.lang.String-org.springframework.http.HttpMethod-org.springframework.http.HttpEntity-java.lang.Class-java.util.Map-
as well as probably another thing or two that I've forgotten about.
Here is what I'm talking about in Postman. I need to be able to pass both of the parameters given here. It works fine if run through Postman, but I can't figure it out in Java/Spring Boot.
Here is a code snippet from the restTemplate.exchange attempt:
public String makeMMSICall(String uri, List<String> MMSIBatchList, HashMap<String, String> headersList) {
ResponseEntity<String> result = null;
try {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
for (String key : headersList.keySet()) {
headers.add(key, headersList.get(key));
}
Map<String, String> params = new HashMap<String, String>();
params.put("mmsi", String.join(",", MMSIBatchList));
params.put("limit", mmsiBatchSize);
HttpEntity<?> entity = new HttpEntity<>(headers);
result = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class, params);
System.out.println(result.getBody());
} catch (RestClientException e) {
LOGGER.error("Exception in makeGetHTTPCall :" + e.getMessage());
throw e;
} catch (Exception e) {
LOGGER.error("Exception in makeGetHTTPCall :" + e.getMessage());
throw e;
}
return result.getBody();
}
Thanks for helping!
You can try java.net.HttpUrlConnection, it works for me but indeed I normally use a POST
HttpURLConnection connection = null;
BufferedReader reader = null;
String payload = "body";
try {
URL url = new URL("url endpoint");
if (url.getProtocol().equalsIgnoreCase("https")) {
connection = (HttpsURLConnection) url.openConnection();
} else {
connection = (HttpURLConnection) url.openConnection();
}
// Set connection properties
connection.setRequestMethod(method); // get or post
connection.setReadTimeout(3 * 1000);
connection.setDoOutput(true);
connection.setUseCaches(false);
if (payload != null) {
OutputStream os = connection.getOutputStream();
os.write(payload.getBytes(StandardCharsets.UTF_8));
os.flush();
os.close();
}
int responseCode = connection.getResponseCode();
}
There's no way of implementing it via RestTemplate, even with .exchange method. It'll simply not send the request body for GET calls even if we pass the entity within the function parameters.(Tested via interceptor logs)
You can use the Apache client to solve this issue/request (whatever you'd like to call it). The code you need is something along following lines.
private static class HttpGetWithBody extends HttpEntityEnclosingRequestBase {
JSONObject requestBody;
public HttpGetWithBody(URI uri, JSONObject requestBody) throws UnsupportedEncodingException {
this.setURI(uri);
StringEntity stringEntity = new StringEntity(requestBody.toString());
super.setEntity(stringEntity);
this.requestBody = requestBody;
}
#Override
public String getMethod() {
return "GET";
}
}
private JSONObject executeGetRequestWithBody(String host, Object entity) throws ClientProtocolException, IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
try{
JSONObject requestBody = new JSONObject(entity);
URL url = new URL(host);
HttpRequest request = new HttpGetWithBody(url.toURI(), requestBody);
request.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
request.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
HttpResponse response;
if(url.getPort() != 0) response = httpClient.execute(new HttpHost(url.getHost(), url.getPort()), request);
else response = httpClient.execute(new HttpHost(url.getHost()), request);
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
JSONObject res = new JSONObject(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
httpClient.close();
return res;
}
}catch (Exception e){
log.error("Error occurred in executeGetRequestWithBody. Error: ", e.getStackTrace());
}
httpClient.close();
return null;
}
If you inspect even Apache client library doesn't support passing the body natively(checked via code implementation of HttpGet method), since contextually request body for a GET request is not a good and obvious practice.
Try creating a new custom RequestFactory.
Similar to
get request with body

cURL GET request with body in Java

I have the following curl request:
curl -X GET http://hostname:4444/grid/api/hub -d '{"configuration":["slotCounts"]}'
which returns a JSON object.
How can I make such request and get the response in Java? I tried this:
URL url = new URL("http://hostname:4444/grid/api/hub -d '{\"configuration\":[\"slotCounts\"]}'");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(
url.openStream(), "UTF-8"))) {
for (String line; (line = reader.readLine()) != null;) {
System.out.println(line);
}
}
But it returns an exception:
Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL: http://hostname:4444/grid/api/hub -d '{"configuration":["slotCounts"]}'
Based on the comments, managed to solve it myself.
private static class HttpGetWithEntity extends
HttpEntityEnclosingRequestBase {
public final static String METHOD_NAME = "GET";
#Override
public String getMethod() {
return METHOD_NAME;
}
}
private void getslotsCount() throws IOException,
URISyntaxException {
HttpGetWithEntity httpEntity = new HttpGetWithEntity();
URL slots = new URL("http://hostname:4444/grid/api/hub");
httpEntity.setURI(pendingRequests.toURI());
httpEntity
.setEntity(new StringEntity("{\"configuration\":[\""
+ PENDING_REQUEST_COUNT + "\"]}",
ContentType.APPLICATION_JSON));
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(getPendingRequests);
BufferedReader rd = new BufferedReader(new InputStreamReader(response
.getEntity().getContent()));
// At this point I can just get the response using readLine()
System.out.println(rd.readLine());
}
That's not how sending data in Java works. The -d flag is for the CURL CLI only. In Java you should use a library like Apache HTTP Client:
https://stackoverflow.com/a/3325065/5898512
Then parse the result with JSON: https://stackoverflow.com/a/5245881/5898512
As per your exception/error log, it clearly says that the service http://hostname:4444/grid/api/hub is receiving bad request(Status code 400).
And i think you need to check the service to which you are hitting and what exactly it accepts. Ex: the service may accept only application/json / application/x-www-form-urlencoded or the parameter to service that expecting but you are not sending that.

Error 407 when trying to send a request in Java

I have the following code:
public class SendRequest {
public static void main(String[] args) throws ClientProtocolException, IOException {
String url = "http://backoffice.xyz";
HttpHost proxy = new HttpHost("proxy.proxy", 8080, "http");
HttpClient client = HttpClientBuilder.create().setProxy(proxy).build();
HttpGet request = new HttpGet(url);
//request.addHeader("User-Agent", "USER-AGENT");
HttpResponse response = client.execute(request);
System.out.println("Response Code: " + response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while((line = rd.readLine()) != null){
result.append(line);
}
System.out.println(result.toString());
}
}
This is returning a 407 Unauthorized Access/Cache Access Denied Error. What code do i need to include so i can authenticate through the proxy?
Does your proxy require username/password based authentication? If so, try implementing java.net.Authenticator. I guess you will need to set useSystemProperties
Authenticator.setDefault(new Authenticator(){
PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication(username, password);
}
});
You might need to add setDefaultCredentialsProvider(CredentialsProvider credentialsProvider) to the HTTPClientBuilder and use SystemDefaultCredentialsProvider instance for that.
1.Can you check your proxy ?? I'm not sure if proxy.proxy is correct.
Your rest of the code seems fine.
2.And also make sure you are updating httpcore version to 4.4 or above. And also you can update httpcore to latest version.
3.You could check the authentication of your proxy as #Goutham mentioned
Hope this helps!!

HTTP PATCH request in Java

I am trying to make a HTTP PATCH request in Java, but despite my efforts this is not working.
I am trying to PATCH a Json, here is my code:
HttpResponse response = null;
BufferedReader rd = null;
StringBuffer result = new StringBuffer();
String line = "";
HttpClient httpclient = HttpClients.createDefault();
HttpPatch httpPatch = new HttpPatch("http://myURL");
JsonArrayBuilder Abuilder = Json.createArrayBuilder();
JsonObjectBuilder oBuilder = Json.createObjectBuilder();
for(int i=0;i<48;i++){
Abuilder.add(i+1);
}
oBuilder.add("date", "2016-09-08");
oBuilder.add("values",Abuilder);
JsonObject jo = Json.createObjectBuilder().add("puissance", Json.createObjectBuilder().add("curves",Json.createArrayBuilder().add(oBuilder))).build();
try{
//Execute and get the response.
StringEntity params =new StringEntity(jo.toString());
params.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httpPatch.setEntity(params);
response = httpclient.execute(httpPatch);
System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
while ((line = rd.readLine()) != null) {
System.out.println(line);
result.append(line);
}
}catch(Exception e){
}
When I execute this request, I get a
"400 Error: The request has an invalid header name".
When I execute this request using Postman, this is working fine.
I am quite new at HTTP requests so do not hesitate to ask if you need more details.
StringEntity.setContentEncoding is used to set the Encoding type,
You should use StringEntity.setContentType to set the ContentType
Problem-
RestTemplate restTemplate = new RestTemplate();
restTemplate.patchForObject("http://localhost:8080/employee/1", requestBody, String.class);
Solution-
RestTemplate restTemplate = new RestTemplate();
restTemplate.postForObject("http://localhost:8080/employee/1?_method=patch", requestBody, String.class);

Fiddler doesn't capture Apache HttpClient post

Somehow Fiddler doesn't capture the posts I send from my HttpClient provided by Apache.
But when I send the same post in C# using the HttpClient to the same server, Fiddler does intercept the sessions.
My Java code:
private DefaultHttpClient client = new DefaultHttpClient();
private HttpContext context = new BasicHttpContext();
private BasicCookieStore store = new BasicCookieStore();
public Client() throws URISyntaxException {
context.setAttribute(ClientContext.COOKIE_STORE, store);
logIn();
}
private void logIn() throws URISyntaxException {
HttpUriRequest login = RequestBuilder.post()
.setUri(new URI("http://www.derpforum.nl"))
.addParameter("username", "Kattoor4")
.addParameter("password", "XXXX")
.addHeader("Referer", "http://www.derpforum.nl/")
.build();
try (CloseableHttpResponse response = client.execute(login, context)) {
HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));
String line;
while ((line = reader.readLine()) != null)
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
}
Any thoughts? Thanks!
I am usring Apache HttpClient(4.5.5), SWT4 and Fiddler4, and the VM arguments method does not work for me.
So I set the proxy settings in the code and it works.
HttpHost proxy = new HttpHost("localhost", 8888, "http");
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
CloseableHttpClient httpclient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.build();
You probably need to configure Java to use Fiddler as a proxy either in code or by setting the relevant Java system properties as below. See this question.
-Dhttp.proxyHost=127.0.0.1
-Dhttp.proxyPort=8888

Categories