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.
Table of Contents:
What Is A Web Service?
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, 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 the 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, the flight vendor’s site sends back JSON/XML response to MakeMyTrip, and they convert the received response and display details in UI.
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.
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 the 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 languages 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 the 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.
#2) Delete dummy packages provided by MAVEN i.e. “src/main/java” and “src/test/java”
#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 Core library:
JSON Parser library:
TestNG library:
#6) Download the latest and most stable versions. We will not add Selenium jar in our project, as we are doing complete backend testing. The final pom.xml file looks like as shown below image:
#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.
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.
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.
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:
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 the 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, a few codes are listed below:
- 200: Ok, everything is working fine.
- 201: Created successfully, whenever you are doing a POST call or creating a new entity.
- 400: Payload is wrong, end URL is wrong, shows bad request.
- 404: Update or delete an entity if that entity is not available, then we get the result as a not found request.
- 500: Suppose the 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.
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 a response. Then store the response.
- Need status code, headers.
Refer to the below screenshot of the POSTMAN client that displays a GET call response:
In restClient.java class,
(i) Create the GET Method which will call the URL and get the response in the form of a JSON object without a 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”
#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, the POST call operation is always used to create 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.
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()));} }
#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
#4) Delete Call
The 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 the 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"); }
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 service types and the importance of JSON/XML files and why they are used.
PREV Tutorial | FIRST Tutorial