Web Services Testing Using Apache HTTP Client

This Tutorial is about Performing various CRUD Operations on Web Services and Testing Web Services using Apache HTTP Client:

In this Complete API Testing Tutorial Series, we have learned that Web Services acts as a medium of communication between client and server machines that interact over a network. We explained all about API Testing Using POSTMAN in our previous tutorial.

In this article, we will emphasize on how to test Web Services using Apache HTTP Client and perform different CRUD operations on Web Services. Different types of REST clients available for backend testing will also be discussed.

What Is A Web Service?

Web Services Testing Using Apache HTTP Client

Web Services are a medium of communication between client and server machines that interacts over a network with the help of HTTP protocols. Web services are generally APIs that are not installed or stored locally but are available in clouds or in some remote servers.

Refer to the example below to understand how web services work.

MakeMyTrip.com and Goibibo.com are some of the famous flight and hotel booking websites and there are different flight vendors available like Indigo, Air India, and Etihad, etc.

If a customer wants to book a flight from New York to London, either they can browse directly on the flight vendor portal or they can book through third-party vendors. If they are booking through third-party vendors like MakeMyTrip and other booking sites, within a few seconds they will compare and show results providing flight details like lowest price, flight time, and much more other information.

The question that arises here is, how exactly, within seconds, are they providing us with the information? What exactly do they do?

From UI, they take all the necessary information and store it in a JSON or XML file and call their vendor APIs with an authentication token as they expose their APIs, and in response, flight vendor’s site sends back JSON/XML response to MakeMyTrip, and they convert the received response and display details in UI.

Web Services interface

Types of Web Services

There are two types of web services, namely

  • SOAP API
  • REST API

Let us see the differences between these two web services as enlisted in the below image.

Differences between SOAP and REST

JSON/XML Files In Web Service

Let S1 system is returned in J2EE language and the S2 system is returned in .NET or Python and we know that both technologies are completely different from each other with security concern too. Then how will the S2 system share the code with another system?

So, the S2 system exposes its APIs to the S1 system without exposing business logic, and the S2 system shares API name, API URL, API format, and Authentication key/Token Key to access its system. Communication happens between the two systems using either JSON or XML files.

Why JSON/XML file only?

JSON/XML files are used because these are data collectors. Any particular information is stored either in JSON or XML formats, as these are lightweight and they are standard language to communicate between two different interfaces/platforms or systems.

So, API is always used when two independent systems interact with each other, either locally, within the system, or over the network.

What Is a REST Client?

REST Client is a tool that calls the APIs. It is used in backend testing when there is no UI to call the APIs. Some popular REST clients are Apache HTTP client, POSTMAN, SOAP UI, Swagger, and many more.

Here, in this article, we will only discuss Apache HTTP client and we will cover other different HTTP clients in our future articles.

Http Client Setup In Eclipse

#1) Open Eclipse and create a new Maven Project.

Create a new Maven Project

#2) Delete dummy packages provided by MAVEN i.e. “src/main/java” and “src/test/java”

Delete dummy packages provided by MAVEN

#3) Go to the pom.xml file and remove the JUnit dependency as we don’t need it.

#4) Then, we require the HTTP Client library, HTTP Core library, JSON Parser library, TestNG library, Jackson-data bind Library

#5) Add above dependencies(library) in pom.xml file.

HTTP Client library:

HTTP Client library

HTTP Core library:

HTTP Core library

JSON Parser library:

JSON Parser library

TestNG library:

TestNG library

#6) Download the latest and stable versions. We will not add Selenium jar in our project, as we are doing complete backend testing. Final pom.xml file looks like as shown in below image:

Final POM.xml file

#7) Next, create a framework for your API test

a) Create a package “com.qa.config” -> Create a file “config.properties” and store all URLs.

Create a package “com.qa.config”

b) Create another package “qa.com.base” -> Create a class “testBase.java” which will be a parent class for all over classes. It contains common functions to be used by all methods.

Another package “qa.com.base”

c) Create another package “com.qa.client” and class “restClient.java”. This contains code to fetch GET, POST, DELETE, PUT calls.

d) Create another package “com.qa.data” and class “user.java” which defines different user properties.

package “com.qa.data” and class “user.java”

e) Finally, create a package “com.qa.Test” under “src/test/java” and declare a main method and functions to test all GET, PUT, POST, and Delete methods.

f) Final framework structure will look like as shown below:

Final framework structure

g) Use dummy API provided by this site REQ RES.

HTTP Methods Or CRUD Operations

Let us see different HTTP methods or CRUD operations that we automate.

Below listed operations are called CRUD operations:

  • C: Create (means POST call)
  • R: Retrieve (means GET call)
  • U: Update (means PUT call)
  • D: Delete (means Delete call)

Parameters In REST Web Services

Validate or emphasize below parameters in REST Web Services :

(i) URI: URI is the combination of the URL+Path parameter and the query parameter.

Example: http://api.com/service/account/1

Here, api.com is the URL for the S2 server, service is the holder. In this service, the holder goes to the account class, and from this account class, it calls the method account =1. In each and every call we pass the URI.

(ii) Payload: JSON/XML data that we feed to the system.

(iii) Status Code: For each and every response, we get the status codes.

Here, few codes are listed below:

  • 200: Ok, everything is working fine.
  • 201: Created successfully, whenever you are doing POST call or creating a new entity.
  • 400: Payload is wrong, end URL is wrong, shows bad request.
  • 404: Update or delete an entity and that entity is not available, then we get result as not found request.
  • 500: Suppose S2 server is down, we get an internal server error.
  • 401: Authentication error

Click here to get all the status codes.

(iv) Headers: Like Authentication token, User id/password, Content-Type, etc.

Headers

CRUD Operations Using Apache HTTP Client

#1) GET Call

How GET Call operation behaves?

Get Call sends the request and receives back the response. We don’t pass any JSON or the payload here, we pass one URI, in which URL (endpoint path parameter, query parameter) along with the header, if available.

Before writing the GET Call code, keep below things in mind:

  • Need a GET method
  • Then need a URL
  • Once you hit the send button, you will get the response. Then store the response.
  • Need status code, headers.

Refer the below screenshot of POSTMAN client that displays GET call response:

POSTMAN client

In restClient.java class,

(i) Create the GET Method which will call the URL and get the response in the form of JSON object without Header.

package com.qa.Client;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

public class restClient {

// create GET Method, which will call the URL and get the response in the form of JSON object without Header
public CloseableHttpResponse getMethod(String Url) throws ClientProtocolException, IOException, JSONException{
		
/*Call HTTPClients class from HTTPClient library added in POM.xml.
Call createDefault() method present in HTTPClients class, which will create a client connection.
And this createDefault() method returns "CloseableHttpClient" object which is an abstract class. 
And we are creating a reference to that abstract class */
		
CloseableHttpClient httpClient=HttpClients.createDefault();
		
/*create an object for HttpGet class, which is used for HTTP GET Request. And pass the URL which is to be loaded*/
		
HttpGet htttpGet = new HttpGet(Url); 
		
/*execute the HTTP GET Request, means it will hit the GET API call as we click SEND button from POSTMAN client. 
httpClient.execute() method returns the response "CloseableHttpResponse" interface and store it in reference variable
So the complete response is stored in CloseableHttpResponse
And fetch all the details, in our test case/test method */
		
CloseableHttpResponse closeableHttpResponse = httpClient.execute(htttpGet); 
	return closeableHttpResponse; }
	}

(ii) Create main class “getAPITest.java” under “src/test/java”


Output
Output

#2) POST Call

POST Call creates an account or creates a new entity.
Example – Pass these details like name, job, and header to the JSON payload. S2 server will be linked to some database say Oracle and has some table name called Account table. POST method will create an entry in the database and the S2 server passes the information to the S1 client. Remember that, POST call operation is always used to create a new entity.

POST Call creates an account or creates a new entity

In the POST method, we have to pass the URL and the payload.

Download this dependency as we need to convert Java class to Java object than to JSON object.

dependency

In restClient.java class,

(i) Create POST Method, which will call the URL and post the response.

public class restClient {

public CloseableHttpResponse POST(String url,String entityString,HashMap<String,String> headermap) throwsClientProtocolException, IOException{

/*Call HTTPClients class from HTTPClient library added in POM.xml and createDefault() method present in HTTPClients class, 
which will create a client connection and this createDefault() method returns "CloseableHttpClient" object which is an abstract class 
and we are creating reference to that abstract class */
		
CloseableHttpClient httpClient=HttpClients.createDefault();
		
/*create an object for HttpPost class, which is used for HTTP POST Request and pass the URL which is to be loaded */
		
HttpPost htttpPost = new HttpPost(url); 
		
/*define pay load, use setEnity method present in HTTPPOST class and pass the payload entity */

htttpPost.setEntity(new StringEntity(entityString));
			
//Create a for loop and iterate the hashmap, and store the header

for(Map.Entry<String,String> entry : headermap.entrySet()){
	htttpPost.addHeader(entry.getKey(),entry.getValue());
}
		
//Execute the  POST request
CloseableHttpResponse closeableHttpResponse = httpClient.execute(htttpPost);
	return closeableHttpResponse;
	}
}

(ii) Create the main class “postAPI_Test.java” under “src/test/java”.

//Inherit testBase class
public class postAPI_Test extends testBase {

//Create global methods
	testBase testbase;
	String serviceURL;
	String apiURL;
	String URL;
	restClient restClient;
	HttpResponse closeableHttpResponse;
		
// In before method call the properties file
@BeforeMethod
public void setUp() throws ClientProtocolException, IOException, JSONException{
		
//call the constructor of base class and execute the properties file
testbase = new testBase();
serviceURL = prop.getProperty("URL");
apiURL = prop.getProperty("serviceURL");
URL = serviceURL+apiURL;
		}
		
//Main method which calls the GET method	
@Test
public void POSTAPITest() throws ClientProtocolException, IOException, JSONException{
			
	restClient = new restClient();
			
//Pass the Request Header
HashMap<String,String> headrMap = new HashMap<String,String>();
headrMap.put("Content-Type", "application/json");
			
/*Use Jackson API for doing marshaling, means converting java to java object to JSON Object 
and vice versa Use ObjectMapper class */
ObjectMapper  mapper = new ObjectMapper();
			
//Create object of Users class, expected users
users user = new users("John","Manager");
			
//Convert java object "user" to JSON Object using writeValue(), pass the path 
where to store the JSON file and the object to be converted */
mapper.writeValue(new File(".\\data\\users.json"), user );
			
//convert java object to json in string
String userJsonString = mapper.writeValueAsString(user);
System.out.println(userJsonString);
			
//Call the POST Method
closeableHttpResponse = restClient.POST(URL, userJsonString, headrMap);
			
//Fetches status, header, and JSON response from CloseableHttpResponse

//1.Fetch Status Code
int statusCode = closeableHttpResponse.getStatusLine().getStatusCode();//Get the Status code
System.out.println("Status Code --->" +statusCode);
			
//Validate the status code using Assert class
Assert.assertEquals(statusCode, response_Status_Code_201,"Status is not 200");
					
/*2.Fetch the JSON String use EntityUtils class and call to String method, where we have to pass entity 
and format entity is available in closeableHttpResponse and pass UTF-8 format because we want pure string 
so complete JSON will be stored in a String, so we need to convert an entire string into a JSON object */

String responseString = EntityUtils.toString(closeableHttpResponse.getEntity(), "UTF-8");
						
/*as we added one JSON library, from that library call JSON class and pass the response string. 
So this JSON object converts the string into JSON */ 
JSONObject responseJson = new JSONObject(responseString);
System.out.println("Response JSONfrom API --->"+responseJson);
			
/*Convert JSON to java actual User Object we are getting */
users userResObj = mapper.readValue(responseString, users.class);

Assert.assertTrue(user.getName().equals(userResObj.getName()));
Assert.assertTrue(user.getJob().equals(userResObj.getJob()));}		

 }

Output:
Output_POST Call

#3) PUT Call

Using the PUT call operation, you can create a new entity and update an existing entity.

In restClient.java class,

(i) Create PUT Method, which will call the URL and update the response.


public class restClient {

public CloseableHttpResponse PUT(String url,String entityString,HashMap<String,String> headermap) throwsClientProtocolException, IOException{
		
/*Call HTTPClients class from HTTPClient library added in POM.xml. Call createDefault() method present in HTTPClients class, 
which will create a client connection and this createDefault() method returns "CloseableHttpClient" object which is an abstract class 
and we are creating reference to that abstract class*/

CloseableHttpClient httpClient=HttpClients.createDefault();
		
/*create an object for HttpPut class, which is used for HTTP PUT Request and pass the URL which is to be loaded */

HttpPut htttpPut = new HttpPut(url); 
		
/*define pay load, use setEnity method present in HTTPPUT class and pass the payload entity */

htttpPut.setEntity(new StringEntity(entityString));
			
/*create a for loop, iterate and store the header */

for(Map.Entry<String,String> entry : headermap.entrySet()){
htttpPut.addHeader(entry.getKey(),entry.getValue());
		}
		
//Execute the PUT request

CloseableHttpResponse closeableHttpResponse = httpClient.execute(htttpPut);
return closeableHttpResponse; }
}

(ii) Create the main class “putAPI_Test.java” under “src/test/java”


//Inherit testBase class
public class putAPI_Test extends testBase {

//Create global methods
	testBase testbase;
	String serviceURL;
	String apiURL;
	String URL;
	restClient restClient;
	HttpResponse closeableHttpResponse;
		
// in before method call the properties file
@BeforeMethod
public void setUp() throws ClientProtocolException, IOException, JSONException{
		
//Call the constructor of the base class and execute the properties file
	testbase = new testBase();
	serviceURL = prop.getProperty("URL");
	apiURL = prop.getProperty("serviceURL");
	URL = serviceURL+apiURL;
}
		
//Main method which calls PUT method	
@Test
public void PUTAPITest() throws ClientProtocolException, IOException, JSONException{
			
	restClient = new restClient();
			
//Pass the Request Header
HashMap<String,String> headrMap = new HashMap<String,String>();
headrMap.put("Content-Type", "application/json");
			
/*use Jackson API, for doing marshaling means converting java to java object to JSON Object and vice versa, 
use ObjectMapper class */

ObjectMapper  mapper = new ObjectMapper();
			
//Create object of Users class, new users
users user = new users("JohnMarry Dicosta","HRManager");
			
/*Convert java object "user" to JASON Object using writeValue() 
and pass the path where to store the JSON file and the object to be converted */

mapper.writeValue(new File(".\\data\\users.json"), user );
			
//convert java object - > JSON - >String
String userJsonString = mapper.writeValueAsString(user);
System.out.println(userJsonString);
			
//Call the PUT Method
closeableHttpResponse = restClient.PUT(URL, userJsonString, headrMap);
			
/*fetch status, header, JSON response from CloseableHttpResponse 
Fetch Status Code */

int statusCode = closeableHttpResponse.getStatusLine().getStatusCode();
System.out.println("Status Code --->" +statusCode);
			
//Validate the status code using Assert class
Assert.assertEquals(statusCode, response_Status_Code_200,"Status is 200");
					
/*2.Fetch the JSON String, use EntityUtils class and call to String method where we have to 
pass entity and format entity is available in closeableHttpResponse and pass UTF-8 format 
because we want a pure string. So complete JSON will be stored in a String, so we need to 
convert an entire string into a JSON object */

String responseString = EntityUtils.toString(closeableHttpResponse.getEntity(), "UTF-8");
						
/* From JSON library, call JSON class and pass the response string. 
This JSON object converts the string to JSON */
JSONObject responseJson = new JSONObject(responseString);
System.out.println("Response JSONfrom API --->"+responseJson);}

Output

Putcall-output

#4) Delete Call

Delete call operation is simple, i.e. delete the account id- 100 and pass the information in a JSON file.

In restClient.java class,

(i) Create Delete Method, which will call URL and delete the record.


public CloseableHttpResponse Delete(String url) throws ClientProtocolException, IOException{
			
/*Call HTTPClients class from HTTPClient library added in POM.xml and createDefault() method 
present in HTTPClients class, which will create a client connection and this createDefault() method returns 
"CloseableHttpClient" object which is an abstract class and we are creating reference to that abstract class */

CloseableHttpClient httpClient=HttpClients.createDefault();
			
/*create an object for HttpDelete class, which is used for HTTP Delete Request, and pass the URL to be loaded*/

HttpDelete htttpDelete = new HttpDelete(url); 
				
//execute Delete request
CloseableHttpResponse closeableHttpResponse =httpClient.execute(htttpDelete);
return closeableHttpResponse;
}

(ii) Create the main class “deleteAPI_Test.java” under “src/test/java”.


public class deleteAPI_Test extends testBase {

//Create global methods
		testBase testbase;
		String serviceURL;
		String deleteuserUrl;
		String URL;
		restClient restClient;
		HttpResponse closeableHttpResponse;
			
// In before method call the properties file
@BeforeMethod
public void setUp() throws ClientProtocolException, IOException, JSONException{
			
//call the constructor of the base class and execute the properties file
		testbase = new testBase();
		serviceURL = prop.getProperty("URL");
		deleteuserUrl = prop.getProperty("deleteuser");
		URL = serviceURL+deleteuserUrl;
	}
			
//The Main method which calls the Delete method	
@Test
public void deleteAPI() throws ClientProtocolException, IOException, JSONException{
				
        restClient = new restClient();
		
//Method returns closeableHttpResponse type
closeableHttpResponse = restClient.Delete(URL);
		
/*fetch status code, header, JSON response from CloseableHttpResponse -Fetch Status Code */

int statusCode = closeableHttpResponse.getStatusLine().getStatusCode();
System.out.println("Status Code --->" +statusCode);
		
//Validate the status code using Assert class
Assert.assertEquals(statusCode, response_Status_Code_204,"Status is  204 No Content");
					
   }

Output
Delete Call Output

Before validating any response get the correct URL from the developer, then check whether you are getting expected response from the server, prepare test cases for each and every scenario and arrange test cases in sequence w.r.t functionality.

Conclusion

In this article, we have covered how to use Apache HTTP Client for automating POST, PUT, GET, and Delete calls in detail with code examples. We have also discussed web services types and the importance of JSON/XML files and why they are used.

PREV Tutorial | FIRST Tutorial