0% found this document useful (0 votes)
189 views

RESTAPI

This document provides an overview and table of contents for a book on REST API testing using Rest Assured. The book covers topics such as client-server architecture, HTTP requests and responses, API testing with Postman, GET and POST requests, REST fundamentals, testing REST APIs with Rest Assured including validating responses, handling parameters and authentication, JSON, JSONPath, API documentation, end-to-end testing in Cucumber, converting JSON requests and responses to Java objects, and more.

Uploaded by

hsnnycll
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
189 views

RESTAPI

This document provides an overview and table of contents for a book on REST API testing using Rest Assured. The book covers topics such as client-server architecture, HTTP requests and responses, API testing with Postman, GET and POST requests, REST fundamentals, testing REST APIs with Rest Assured including validating responses, handling parameters and authentication, JSON, JSONPath, API documentation, end-to-end testing in Cucumber, converting JSON requests and responses to Java objects, and more.

Uploaded by

hsnnycll
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 274

Page | 1

Page | 2
Page | 3
I dedicate this book
to my beloved husband,
who loves me very much,
puts the world in front of him for me,
and who is always by my side.
Thank you for everything…

Page | 4
Contents
What will you learn in this book? ..................................................................................................................................... 7
What is Client Server Architecture? .................................................................................................................................. 7
What is HTTP Request? ................................................................................................................................................... 10
What is HTTP Response?................................................................................................................................................. 16
API Testing with Postman ............................................................................................................................................... 21
Download Postman and Install On Windows and MacOS .............................................................................................. 25
Postman Navigation ........................................................................................................................................................ 31
Create New Request in Postman .................................................................................................................................... 36
GET Requests in Postman ............................................................................................................................................... 39
Response in Postman ...................................................................................................................................................... 40
Request Parameters in Postman..................................................................................................................................... 45
POST Request using Postman ......................................................................................................................................... 50
What is REST?.................................................................................................................................................................. 57
What is Rest Api? ............................................................................................................................................................ 61
Rest Architectural Elements............................................................................................................................................ 64
Getting started with Rest Assured .................................................................................................................................. 68
Configure Eclipse with Rest-Assured .............................................................................................................................. 71
REST API Testing using Rest Assured .............................................................................................................................. 78
Validate Response Status using Rest Assured ................................................................................................................ 84
Validate Response Header using Rest Assured ............................................................................................................... 90
Read JSON Response Body using Rest Assured .............................................................................................................. 93
Working with Query Parameters in Rest Assured | REST API ......................................................................................... 98
Understanding HTTP POST Request Method using Rest Assured ................................................................................ 101
Serialization and Deserialization in Java ....................................................................................................................... 105
Deserialize JSON Response using Rest Assured ............................................................................................................ 111
Authentication and Authorization in REST WebServices .............................................................................................. 115
Basic Authentication ..................................................................................................................................................... 118
PUT Request using Rest Assured................................................................................................................................... 123

Page | 5
DELETE Request using Rest Assured ............................................................................................................................. 127
What is JSON? ............................................................................................................................................................... 132
JSONPath and Query JSON using JSONPath.................................................................................................................. 134
Expressions in JSONPath ............................................................................................................................................... 141
Deserialize JSON Array to List ....................................................................................................................................... 156
Deserialize JSON Array to an Array ............................................................................................................................... 159
What is API Documentation, and Why It Matters?....................................................................................................... 163
REST API End to End Test .............................................................................................................................................. 171
REST API Test in Cucumber ........................................................................................................................................... 179
Convert JSON Request Body to JAVA Object ................................................................................................................ 190
Convert JSON Response Body to Java Object ............................................................................................................... 205
Separation of Test Layer with API Services ................................................................................................................... 217
Implementation of REST Routes ................................................................................................................................... 226
Implementation of Generics in API Framework............................................................................................................ 232
Refactoring for Request Headers .................................................................................................................................. 242
Share Test Context in Cucumber .................................................................................................................................. 249
Share Scenario Context in Cucumber ........................................................................................................................... 255
Implement Configuration Reader ................................................................................................................................. 263
Rest Assured Examples ................................................................................................................................................. 271

Page | 6
What will you learn in this book?
Rest Assured Tutorial for REST API Automation Testing

This is a series of Rest Assured Tutorial which is one of the most used library
for REST API Automation Testing. Rest-Assured is a Java-based library that is
used to test RESTful Web Services. This library behaves like a headless Client
to access REST web services. We can create highly customize-able HTTP
Requests to send to the Restful server. This enables us to test a wide variety of
Request combinations and in turn test different combinations of core business
logic.

Rest-Assured library also provides the ability to validate the HTTP Responses received from the server. For e.g. we
can verify the Status code, Status message, Headers and even the Body of the response. This makes Rest-Assured a
very flexible library that can be used for testing.

What is Client Server Architecture?


For any web application, the API services work as the building block. Therefore it becomes very important for you, as
a tester, to ensure that the web services are bug-free and facilitate the exchange of information securely. In this
article series, we will cover the automation of Rest API using RestAssured. But before jumping onto it, let us look at
some of the basics to strengthen our knowledge of APIs. One of the basic concepts to start with is by understanding
the client server architecture. In this article, we will understand below points-

• Client server Architecture

o What is a client?

o What is a server?

• How does the client server architecture work?

• Advantages of using client server architecture?

• What are the drawbacks of client server architecture?

What is Client Server Architecture?

Client server architecture in a simple sense can be stated as a consumer-producer model where the client acts as the
consumer i.e. the service requestor and the server is the producer, i.e. the service provider. Let us see how they are
described in the computing sense.

What is a Client?

A client in computing is a system or a program that connects with a remote system or software to fetch information.
The client makes a request to the server and is responded with information. There may be three types of clients -
thick, thin or hybrid client.

• A thick or fat client performs the operation itself without the need for a server. A personal computer is a fine
example of a thick client as the majority of its operations are independent of an external server.

• A thin client uses the host computer's resources, where the thin client presents the data processed by an
application server. A web browser is an example of a thin client.

• A hybrid client is a combination of a thick and a thin client. Just like the thick client it processes data
internally but relies on the application server for persistent data. Any online gaming run on a system can be
an example of a hybrid client.

What is a Server?

Page | 7
A server is a system or a computer program that acts as the data provider. It may provide data through LAN(Local
Area Network) or WAN(Wide Area Network) using the internet. The functionalities provided by the server are called
services. These services are provided as a response to the request made by the clients. Some of the common servers
are-

• Database Server - used to maintain and share the database over a network.

• Application Server - used to host applications inside a web browser allowing to use them without installation
locally.

• Mail Server - used for email communication.

• Web Server - used to host web pages because of which worldwide web is possible.

• Gaming Server - used for playing multiplayer games.

• File Server - used for sharing files and folders over a network.

These clients and servers do not necessarily be at the same location. They could either be located in different
locations or may reside as different processes on the same computer. They are connected via the Web and interact
via the HTTP protocol which will be discussed later in this article. There may be multiple clients requesting a server
and alternatively, a client can request from multiple servers.

Visualising the client server architecture

The below diagram visualizes a typical client-server model-

As shown in the diagram, a single server may serve the requests of multiple clients. Similarly, a client may be
requesting data from different servers. For example, consider an example of Google. Here, Google acts as the server
and the users sitting at different places act as the clients.

Another example that we come across in our everyday life is the Online Banking Portal in which the browser that we
use to open a portal acts as the client while the database and the software for banking act as the server. This
propagates resource sharing across multiple users and thereby results in cost-efficiency along with time saving.

In the next section let us see how the client-server model works and how does this interaction takes place.

How does the Client Server Architecture work?

As already discussed above, the client server model acts like a consumer-server relationship. But how does it work?
Let us see some of the flow of information in a client-server architecture through a series of steps as discussed
below-

1. The HTTP communication protocol helps establish the connection between the client and the server.
Page | 8
2. The client sends a request in the form of an XML or a JSON over the active connection. The client and server
both understand the message format.

3. Upon receiving the client request, the server searches the requested data and sends back the relevant details
as a response in the same format in which the request was received.

The above diagram shows the communication process between the client and the server. The client sends an HTTP
request, for which the server sends an HTTP response. Let us consider an example to understand more about it.

Visualising the flow of client server architecture

Assume that you need to go shopping from your home to a shop across the road. You may travel on a bicycle and on
reaching can order the salesman the goods you need. Now if the salesman finds the goods, he will bring them to you
else he would let you know about their unavailability.

Now, you may link the above example with the navigation to a website, the street between your home and the shop
is the internet connection. The mode of transport that you chose to travel is the TCP/IP, defining the communication
protocol for the data to travel through the internet. The address of the shop is the DNS(Domain Name Server) of the
website. Your communication language with the salesman is the HTTP(Hypertext Transfer Protocol) which defines
the language for interaction between the client and the server. Your order request is the HTTP request and the
update on item availability is the HTTP response.

When the web browser sends a request to the server with the DNS of the website, and the server approves the
client request, it sends a 200 OK success message. This message means that the server has located the website and it
sends back the website files in small chunks of data to the browser. The browser then collects and assembles these
small chunks to form the complete website and displays it to us.

We will discuss more on the HTTP request and response in the next articles.

What are the advantages of using Client-Server Architecture?

Client-server architecture has the following advantages -

• It maintains data at one central location.

• It provides backup and data recovery options.

• Accessing the data from a single server help in cost-efficiency with less maintenance.

• The capacity of the client and the server can be individually modified.

Issues of Client-Server Architecture?

Client-server architecture has the following disadvantages -

• A virus can easily attack a client present on the server.

• In case of network failure, the entire architecture of an application can suffer.

• Man-in-the-middle attack or data spoofing is possible during data transmission.

Page | 9
• Due to vulnerability to different kinds of attacks, it requires a special and secure network operating system.

• Possibility of loss of data packets either completely or modification because of some intrusion during the
transmission.

What is HTTP Request?


In the previous article, we have already seen what the client-server architecture is and how it works using the HTTP
communication protocol. Moreover, we know that HTTP (HyperText Transfer Protocol) is a TCP/IP communication
protocol used for data exchange on the web. Subsequently, now we will understand more about HTTP
Request, which is one of the fundamental units used in API testing. Consequently, in this article, we will cover below
points-

• What is HTTP Request?

o What are the different HTTP Request methods?

o And, what is the structure of an HTTP Request?

• GET vs. POST Method

What is HTTP Request?

As already understood in the client-architecture model, the client sends the request to the server to fetch some
information or data. Additionally, the client's request is an HTTP Request, which communicates between the client
and the server, or you may say, two different computer systems. Moreover, it is a simple text file formatted in
either XML or JSON, which sends the client's binary data to the server. A simple GET HTTP request looks like below-

Moreover, the request URI in this case is -

https://bookstore.toolsqa.com/BookStore/v1/Books

In this link URIs here;) =


{"books":[{"isbn":"9781449325862","title":"Git Pocket Guide","subTitle":"A Working
Introduction","author":"Richard E. Silverman","publish_date":"2020-06-
04T08:48:39.000Z","publisher":"O'Reilly Media","pages":234,"description":"This pocket
guide is the perfect on-the-job companion to Git, the distributed version control
system. It provides a compact, readable introduction to Git for new users, as well as a
reference to common commands and procedures for those of you with Git
exp","website":"http://chimera.labs.oreilly.com/books/1230000000561/index.html"},{"isbn
Page | 10
":"9781449331818","title":"Learning JavaScript Design Patterns","subTitle":"A
JavaScript and jQuery Developer's Guide","author":"Addy Osmani","publish_date":"2020-
06-04T09:11:40.000Z","publisher":"O'Reilly Media","pages":254,"description":"With
Learning JavaScript Design Patterns, you'll learn how to write beautiful, structured,
and maintainable JavaScript by applying classical and modern design patterns to the
language. If you want to keep your code efficient, more manageable, and up-to-
da","website":"http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/"},{"
isbn":"9781449337711","title":"Designing Evolvable Web APIs with
ASP.NET","subTitle":"Harnessing the Power of the Web","author":"Glenn Block et
al.","publish_date":"2020-06-04T09:12:43.000Z","publisher":"O'Reilly
Media","pages":238,"description":"Design and build Web APIs for a broad range of
clients—including browsers and mobile devices—that can adapt to change over time. This
practical, hands-on guide takes you through the theory and tools you need to build
evolvable HTTP services with
Microsoft","website":"http://chimera.labs.oreilly.com/books/1234000001708/index.html"},
{"isbn":"9781449365035","title":"Speaking JavaScript","subTitle":"An In-Depth Guide for
Programmers","author":"Axel Rauschmayer","publish_date":"2014-02-
01T00:00:00.000Z","publisher":"O'Reilly Media","pages":460,"description":"Like it or
not, JavaScript is everywhere these days-from browser to server to mobile-and now you,
too, need to learn the language or dive deeper than you have. This concise book guides
you into and through JavaScript, written by a veteran programmer who
o","website":"http://speakingjs.com/"},{"isbn":"9781491904244","title":"You Don't Know
JS","subTitle":"ES6 & Beyond","author":"Kyle Simpson","publish_date":"2015-12-
27T00:00:00.000Z","publisher":"O'Reilly Media","pages":278,"description":"No matter how
much experience you have with JavaScript, odds are you don’t fully understand the
language. As part of the \\\"You Don’t Know JS\\\" series, this compact guide focuses
on new features available in ECMAScript 6 (ES6), the latest version of the
st","website":"https://github.com/getify/You-Dont-Know-
JS/tree/master/es6%20&%20beyond"},{"isbn":"9781491950296","title":"Programming
JavaScript Applications","subTitle":"Robust Web Architecture with Node, HTML5, and
Modern JS Libraries","author":"Eric Elliott","publish_date":"2014-07-
01T00:00:00.000Z","publisher":"O'Reilly Media","pages":254,"description":"Take
advantage of JavaScript's power to build robust web-scale or enterprise applications
that are easy to extend and maintain. By applying the design patterns outlined in this
practical book, experienced JavaScript developers will learn how to write
flex","website":"http://chimera.labs.oreilly.com/books/1234000000262/index.html"},{"isb
n":"9781593275846","title":"Eloquent JavaScript, Second Edition","subTitle":"A Modern
Introduction to Programming","author":"Marijn Haverbeke","publish_date":"2014-12-
14T00:00:00.000Z","publisher":"No Starch Press","pages":472,"description":"JavaScript
lies at the heart of almost every modern web application, from social apps to the
newest browser-based games. Though simple for beginners to pick up and play with,
JavaScript is a flexible, complex language that you can use to build full-scale
","website":"http://eloquentjavascript.net/"},{"isbn":"9781593277574","title":"Understa
nding ECMAScript 6","subTitle":"The Definitive Guide for JavaScript
Developers","author":"Nicholas C. Zakas","publish_date":"2016-09-
03T00:00:00.000Z","publisher":"No Starch Press","pages":352,"description":"ECMAScript 6
represents the biggest update to the core of JavaScript in the history of the language.
In Understanding ECMAScript 6, expert developer Nicholas C. Zakas provides a complete
guide to the object types, syntax, and other exciting changes that
E","website":"https://leanpub.com/understandinges6/read"}]}

What are the different HTTP Request methods?

HTTP request methods specify the action to perform through the request. These are also known as verbs and
generally used for CRUD operations, i.e., Create, Read, Update & Delete. Moreover, HTTP request methods are case-
sensitive and should always be uppercase. Subsequently, let us see some commonly used HTTP methods:

1. GET - As the name suggests, the Get method fetches the information from the server. Moreover, it is the most
commonly used method which does not have a request body. Every time you open a website, the Get request fires to
retrieve the website contents. Additionally, it is equivalent to the read operation. Some of the main features of the
GET method are-

• We can easily bookmark the data using the GET method.

Page | 11
• The limit of the length of values is generally 255 characters for the GET method.

• GET supports only string data types.

• GET requests are cacheable.

• The parameters passed in GET methods store in the browser history.

An example GET request would look like this -

GET https://bookstore.toolsqa.com/BookStore/v1/Books HTTP/1.1

2. HEAD: The Head method is similar to the Get method, but it retrieves only the header data and not the entire
response body. Moreover, we use it when you need to check the document's file size without downloading the
document.

3. POST: The Post method works to send data to the server. You may add or update data using the Post request. We
send the information that needs to update in the request body. In the real world, the form data on website updates
using the Post request. Some of the critical features of a POST method are-

• Data passed through the POST method is not visible in the browser URL.

• Additionally, values passed through POST are not stored in browser history.

• Moreover, there is no restriction on the length of data sent through the POST method.

• Also, POST method request supports different data types like String, binary, integers, etc.

4. PUT: The Put method is similar to the Post method since it updates the data. The only difference is that we use it
when we have to replace an existing entity completely. Also, PUT methods are idempotent, i.e., they return the same
result on executing repeatedly.

5. PATCH: This method is again similar to Post and Put methods, but we use it when we have to update some data
partially. Moreover, unlike the Post and Put methods, you may send only the entity that needs updation in the
request body with the Patch method.

6. DELETE: Like its name, the Delete method deletes the server's representations of resources through the specific
URL. Additionally, just like the Get method, they do not have a request body.

7. OPTIONS: This is not a widely used method when compared to other ones. It returns data specifying the different
methods and the operations supported by the server at the given URL. Moreover, it responds with an Allow header
giving a list of the HTTP methods allowed for the resource.

Let us now see how the structure of a simple HTTP request looks.

What is the structure of an HTTP Request?

The next step is to understand how an HTTP request looks like and how it is structured. An HTTP request consists of-

1. Request Line

2. Zero or more headers

3. An optional request body

Let us now see what these components are, but before doing that, let's see a simple BookStore REST API developed
by ToolsQA.

• Resource URL: https://bookstore.toolsqa.com/

• Parameter: BookStore/v1/Books

On combining the above two parts, our Request URL becomes-


Page | 12
https://bookstore.toolsqa.com/BookStore/v1/Books

Now you need to open a browser window and hit this URL. Subsequently, you can open the browser developer tools
and navigate the Network tab as highlighted in the image below before you hit the URL.

Once you hit the URL, you will see some requests being sent; you need to click on the first one highlighted below and
see that a detailed request description shows up on the right side.

Conclusively, we are now ready to understand the different components of the HTTP request.

Request Line

Request Line is the very first line in an HTTP request. The combination of three parts forms it-

1. The HTTP method used

2. The request URI

3. The HTTP protocol version

Looking back at our example, the Request-Line for our case would look like this:

GET /BookStore/v1/Books HTTP/1.1

HTTP Method

As discussed above, the HTTP Method specifies the action that should perform through the request. Moreover, the
most common methods that you would come across are GET or POST. Subsequently, we will see the difference
between the two later in this post.

Request URI
Page | 13
The Request URI, i.e., the Uniform Resource Identifier, helps identify the resources on which the request applies.
Request URI has a general format, as shown below.

Request-URI = "*" | absoluteURI | abs_path | authority

Let us see some examples of how one can use the above request URI.

1. When we use an asterisk, ',' it implies that the request is going directly to the server and not to a particular
resource. Also, we must use it when the method in the request does not apply to a resource. For example-

OPTIONS * HTTP/1.1

2. Additionally, the abosulteURI form is a must when we make a request to a proxy, which forwards the request
to the valid cache and returns a response. Moreover, an absolute path cannot be empty. If nothing is present,
it should be given as "/ " (the server root) in URI. Example-

GET https://www.toolsqa.com/ HTTP/1.1

3. Moreover, the most common form of the Request-URI is the one that we used in our example. The client
fetches the resource directly from the origin server by creating a TCP connection to port 80 of the host
"bookstore.toolsqa.com", and below lines are sent in request-

GET /BookStore/v1/Books HTTP/1.1 Host: bookstore.toolsqa.com

HTTP Protocol Version

The HTTP Protocol version allows the sender to specify the format of the message as well as its ability to understand
further communications. Additionally, HTTP/1.1 is the standardized protocol version that we use commonly.

Request Header

Using the request header, the client can send additional information to the server about the request as well as the
client itself. Additionally, there can be either zero or more headers in the request, which can define the content type,
authorization specification, Cookie information, etc. Moreover, we can also define the custom headers using the x-
syntax as per requirements. The below snapshot shows the different headers for the HTTP Request we are using as
an example. Additionally, the Request Line is also in a highlight.

In the above request, there are some header fields that you will come across quite frequently while testing APIs.
Consequently, let's have a quick look at them-

• User-Agent: lets the server identify the application, operating system, vendor, and version.

• Connection: controls the network connection. In other words, kill or continues the connection after the
transaction.

• Cache-Control: specifies browser caching policies.


Page | 14
• Accept-Language: indicates what all languages(natural) the client can understand.

Other than the above, some of the common request-header fields used as per the requirement are-

• Accept-Charset

• Accept-Encoding

• Authorization

• Content-Length

• Content-Type

• Cookie

• Expect

• From

• Host

• If-Match

• If-Modified-Since

• In-None-Match

• If-Range

• If-Unmodified-Since

• Max-Forwards

• Proxy-Authorization

• Range

• Referer

• TE

Request Body

The request body sends additional information to the server to fetch data from the request correctly. In our
example, we did not send any Request body after the request header, as shown in the snapshot above. Additionally,
the request body may either be in the form of XML or JSON. Subsequently, in the upcoming articles, we will see
these requests in more detail.

GET vs. POST method

The difference between the GET and the POST method is the most common question in the interviews. Let us see
some main points that differentiate both these methods.

GET POST

Data goes through the header Data flows through the request body

The size of data is limited to 255 characters No limit on the size of data

Since the data passes through the URL, it


Data is secure since it is not exposed
becomes insecure

Page | 15
GET POST

GET requests wait for the response of the


The POST request does not wait for a successful response from the
previous request before sending the next
previous request before hitting the next one.
request

Can be cached It cannot cache.

Can be bookmarked It cannot bookmark.

Better in performance as compared to POST Less efficient in performance as compared to GET as we spend
since the values append to the URL by default some time on including request body values in the POST request

Only string data type is allowed No restriction on data type

Parameters get stored in browser history Parameters don't get stored in browser history

No impact on data if we hit the reload button. The form data reset if we hit the reload button.

Uses application/x-www-form-urlencoded Uses application/x-www-form-urlencoded or multipart/form-data


encoding for binary data

What is HTTP Response?


Every HTTP Response received as a result of an HTTP request sent by the client to the server has a status code. This
status code value tells us if HTTP Response was successful or not. This article is a continuation of our previous article
in which we performed a sample REST API test call. In this article, we will discuss how to validate the HTTP response
status using REST Assured. The content of the post is reflected by the following index:

• Validate HTTP Response Status using Rest Assured

o How to validate HTTP response status code

o Validating the HTTP error status code?

o How to validate HTTP Response Status Line?

Validate HTTP Response Status using Rest Assured

An HTTP response object typically represents the HTTP packet (response packet) sent back by Web Service Server in
response to a client request. An HTTP Response contains:

1. A status.

2. Collection of Headers.

3. A Body.

So when we say we need to validate HTTP response status, we are looking forward to having a mechanism to read
and validate the entire response object including the status, headers, and the body. Hence, we will validate each of
the HTTP response components separately. So in this article, the validation of an HTTP response status will be dealt
with in three parts as follows:

• Validating HTTP Response Status Code.

• How to validate the Error Status Code

• Validating Response Status Line.

Page | 16
As we already know the same REST API returns a response message in XML or JSON format. This format depends on
the Media-Type attribute in the HTTP request.

But then how will the client know what type of response it will get from the API? Well, this is managed by the
response headers. Response Header contains a Content-Type attribute that informs about the type of response
body format.

Consider the Swagger UI example we discussed in earlier articles. Suppose we send a GET request to the Book Store
through our browser as follows:

java curl -X GET "https://demoqa.com/BookStore/v1/Books" -H "accept: application/json"

When the above command executes we obtain the response shown in below screen:

As seen from the above screenshot, the response has a status, headers, and a body. If we check the "Response
headers" section, in the above screen, it has a content-type attribute that has the value along with other attributes.
On validating this header, the client knows what type of response (body) we can expect.

Let us now proceed with validating the status part of the response.

How to validate HTTP response status code

When the client requests a piece of particular information from the server, the server sends a response with a status
code back to the client. The status code that the server returns tells us whether the request was successful or not. If
the request was successful, the server sends the status code in the range of 200-299. If the request was not
successful, then the status code other than the range is returned. We can get the list of HTTP status codes along with
their description on the W3 page.

Rest Assured library provides a package named "io.restassured.response" which has a Response interface. The
Response interface provides methods that can help to get parts of the received response. The following screenshot
shows some of the important methods of the response interface.

Page | 17
The method *getStatusCode() is used to get the status code of the response. This method returns an integer and
then we can verify its value. TestNG Assert* is used to verify the Status Code. Now consider the code given below:

java import static org.junit.Assert.*; import org.testng.Assert; //used to validate response status import
org.testng.annotations.Test; import io.restassured.RestAssured; import io.restassured.response.Response; import
io.restassured.specification.RequestSpecification;

public class RestAssuredTestResponse { @Test public void GetBookDetails() {


// Specify the base URL to the RESTful web service RestAssured.baseURI =
"https://demoqa.com/BookStore/v1/Books";

// Get the RequestSpecification of the request to be sent to the server RequestSpecification httpRequest =
RestAssured.given();

Response response = httpRequest.get("");

// Get the status code of the request.

//If request is successful, status code will be 200

int statusCode = response.getStatusCode();

// Assert that correct status code is returned.

Assert.assertEquals(statusCode /*actual value*/, 200 /*expected value*/,

"Correct status code returned");

The below line of code extracts the status code from the message:

java int statusCode = response.getStatusCode();

The return value "statusCode" is compared with the expected value i.e. 200. If both values are equal, then an
appropriate message is returned.
Page | 18
java // Assert that correct status code is returned. Assert.assertEquals(statusCode /actual value/, 200 /expected
value/, "Correct status code returned");

If you run the above test, you will see that the test passes since the web service returns the status code as 200 as
shown in the below image.

In this manner, we can verify the status code of the response using the "getStatusCode()" method of the response
interface. Please note that since we already knew that the success code here is 200, we wrote the appropriate code.
Your server may respond as success with a code anywhere between 200 and 299. It is best to check that out
beforehand. Let us now move on to discuss how to validate the status code that returns values other than 200 i.e.
error status code.

How to validate the HTTP error status code?

So far the request-response situations are all good and we have only received 200 status codes indicating successful
requests. But this may not be always true in the real world. There can be reasons like the server is down or REST API
not functioning properly or the requests themselves may be problematic. In conclusion, we may face the following
scenarios:

1. The server hosting REST API is down.

2. Incorrect client request.

3. The resource requested by the client does not exist.

4. An error occurs on the server side during the processing of the request.

So when any of the above scenarios occur, the REST API will return an appropriate status code other than 200. The
client in turn has to validate this status code and process it accordingly.

For the ToolsQA Book Store service, let’s create another test with an erroneous scenario. Here we will validate the
HTTP status code returned by Book store Web Service when an invalid parameter is entered.

So here we provide the parameter to get user details. Here we provide nonexistent userId as the parameter. The
code looks as below:

java import static org.junit.Assert.*; import org.testng.Assert; //used to validate response status import
org.testng.annotations.Test; import io.restassured.RestAssured; import io.restassured.response.Response; import
io.restassured.specification.RequestSpecification;

public class RestAssuredTestResponse {

@Test

public void GetPetDetails()

// Specify the base URL to the RESTful web service

RestAssured.baseURI = "https://demoqa.com/Account/v1/User/";

// Get the RequestSpecification of the request to be sent to the server

Page | 19
RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("test");

// Get the status code of the request.

//If request is successful, status code will be 200

int statusCode = response.getStatusCode();

// Assert that correct status code is returned.

Assert.assertEquals(statusCode /*actual value*/, 200 /*expected value*/,

"Correct status code returned");

When we run this test it returns the error code of 401. We can see the result of the test execution below.

Note: We can make a quick change to the code above to make sure the test passes. This change is shown below:

java Assert.assertEquals(statusCode /actual value/, 401 /expected value/, "Correct status code returned");

So here we expect the value returned to be 401 instead of 200, hence the test is passed. Next, we will validate
the "Status line".

How to validate the response status line?

A "Status-Line" is the first line returned in the HTTP response. The status line consists of three substrings:

• HTTP protocol version.

• Status Code.

• Status Code’s string value.

For example, when the request is successful the status line will have the value "HTTP/1.1 200 OK". Here, the first
part is the HTTP protocol (HTTP/1.1). Next is the HTTP status code (200). The third is the status message (OK).

We can read the entire status line using the method getStatusLine () of the response interface. The following code
shows the demonstration.

java @Test public void GetBookDetails() {


// Specify the base URL to the RESTful web service RestAssured.baseURI =
"https://demoqa.com/BookStore/v1/Books"; // Get the RequestSpecification of the request to be sent to the server
RequestSpecification httpRequest = RestAssured.given(); Response response = httpRequest.get("");

// Get the status line from the Response in a variable called statusLine

String statusLine = response.getStatusLine();


Page | 20
Assert.assertEquals(statusLine /*actual value*/, "HTTP/1.1 200 OK"

/*expected value*/, "Correct status code returned");

Here we perform a similar test as we have done for the status code. We read the status line using the getStatusLine
() method into a string value. Then we compare this returned value with "HTTP/1.1 200 OK" to check if the status is
successful.

Note: The postman article on the same topic (Response in Postman) can be found at Response in Postman.

You asked me the links for the books honey do u remember? At this link you will learn postman in these sections OK?

API Testing with Postman


Welcome to this course about Postman. My name is Harish Rajora and I will be the driver of your ride towards this
journey which will take you inside the depths of Postman.

This tutorial is completely designed for you to understand Postman even though you have never heard of Postman
or let's say API. Since Postman is an API testing tool, we must know what is an API. So in this tutorial, we will explore
the different topics around API such as

• What is an API

• API Testing

• Role of A software tester in API testing

• API Testing and Unit Testing.

• Area for covering your test

Starting with the first, we will start our journey now by learning about APIs.

What is an API?

API stands for Application Programming Interface. Talking in technical terms an API is a set of procedures, functions,
and other points of access that an application, an operating system, a library, etc., makes available to programmers
in order to allow it to interact with other software. Didn't get it? Well, neither did I. Let's break these terms and
explore more about APIs.

Taking an analogy here, let say you went to a restaurant. There is no waiter present, so you need to see the menu
lying on the table and then make a request to the kitchen where the chef will prepare the dish for you. But it does not
always work that way. What if the dish is not available? You will have to go to your seat again and decide something
else. There will be many customers present in the restaurant which will slow the process of the chef since now he will
be listening to the orders instead of preparing them. Also, how can we forget we live in this multilingual world? What
if you do not understand the chef's language? We need a waiter here. A waiter is what can be seen as an API in the
internet world. The waiter will come and take your requests, give them to the chef, and then in response bring back
the food. This waiter is bilingual and speaks both of your (chef and you) languages fluently. What if the dish is not
available? Well, the waiter knows beforehand you made the wrong request, so he will tell you then and there on the
table that the food item is not available. How much time and energy is saved? This is exactly what an API does.

Page | 21
As we visually depict the above analogy using an image, we can see that you are working as a user in the API world.
You make the requests while the waiter works as an API who is an intermediary and takes the request to the
appropriate server. This server will be processing your request and responding back to you. As said above, your
server or application is the chef who is in the kitchen. He will process your request, cook your desired food and
present it back to you as a response. The methods and parameters will be discussed in detail later but here in the
analogy, you can think of it as the special requests you make according to your taste and liking. For example, you
order something from the menu and describe explicitly that it should be extra spicy. This will help the chef to cook
according to your demands.

Page | 22
An API takes your requests from the device and fetches the response from the server. Today, API is everywhere. We
have achieved so much through APIs, it's hard to count. If you are into computer science or IT industry, there is no
escape from APIs. APIs help you fetch a particular response according to the particular request. For example, while
you are booking a flight, you will require specific flight results according to the source, destination and departure
date, and maybe some other variables. For this, you might have to visit different airlines to check their different
price. But through APIs, this is not so difficult. Through different APIs of different airlines, we can get the response of
each and every airline for that specific query at one place like GoIbibo does. Maybe now you must have got the idea
of how vastly APIs are used today. We all are connected through APIs. All the services that are offered online are
mostly through API. As I said, APIs are everywhere

API Testing

So now that we have established what an API is and why APIs are critical to modern interconnected, globally
distributed applications and services, it is important to understand why API testing is critical.

API testing creates a more reliable code. But historically, testing would take place at the GUI level. When a developer
would finish their work, they would hand it off to the QA engineer. The engineers had limited time so they would
test the code at the highest level - the GUI. This would cover both the front-end and the back-end development.

This worked for manual testing and for the beginning of automation testing but isn’t right for the age of agile and
continuous testing. GUI testing is too brittle, GUI automated scripts break easily and are more time-consuming. But
more importantly, when the application is underdeveloped, teams can’t wait for the entire system to be updated
and the GUI to be ready before testing occurs.

In the age of agile, testing must take place at a lower level, i.e at the API level as early as possible. Developers can
even do it themselves. API's can be tested even when the GUI of the application is not yet ready. On top of that API
tests, because of “API contracts”, can even be created before development is complete.

An API or rather all the API present in the software/application should be tested perfectly. This is the job of a
software tester and bears a huge responsibility. A perfect working API leads to the perfect working application.
Testing the API solves a lot of issues in the application which may arise at some point of time in the future. There are
much software available for API Testing and one such software is Postman.

Roles & Responsibilities of a Software tester for testing API's

As an API tester, you should have good architectural knowledge of various web services, REST, SOAP and Micro
Services.

1. Should able to use all the web methods like GET, POST, DELETE, etc

2. Validate the response, response time, error code

3. Able to validate the XML and JSON body by using Json parsers

4. Must know to use OAuth and OAuth2 authentication mechanisms

5. Load and Security testing on web services

6. Able to read and understand the API documentations

Page | 23
7. Able to derive a good number of test cases and scenarios.

8. Should be good in SQL queries to validate API and DB data elements

9. Become master in a tool of your own choice SOAP UI and Postman are not Automation tools. Rest Assured,
Rest Sharp, Node modules are the open source libraries for API testing.

API Testing and Unit Testing

API testing and unit testing are considered the same thing by some testers but actually, it is different. Unit testing is
done by the Developers or by Test Engineers and is done on a class by class basis or on the single component
level. Motive is to verify whether the module delivers the required functionality. The development team monitors
unit testing activity and makes necessary changes wherever required. A major emphasis is on the fact whether each
unit or module works perfectly fine in isolation. That is, dependency should be least to ensure a robust module
design.

On the other hand, API testing is basically black box testing which is simply concerned with the final output of
the system under test. API tests are executed only after the build is ready and portray the system as a whole as it is
the user interface that an end user will interact with.

API testing primarily aims to test the business logic layer of the system's architecture. API testing is primarily handled
by the QA team, which requires them to run any API on top of a particular build meant to serve a specific purpose.

API testing also tests the unit as part of a system, while unit testing typically tests the unit in relative isolation
from the rest of the system. Hence API testing is also end to end testing. This simply means when we test the
complete software in API testing then the modules which make that software are also tested, obviously. But when
we do unit testing, we focus only on the functionality of that module and see its working which is completely
isolated from the rest of the modules/software.

Area for covering your test

When we test any API through a tool, we face a lot of errors normally. These errors are not only related to only APIs
but can vary from software error to server error. This makes the job of a software tester more important and wide
than it seems. Since a software is built and delivered in steps, same goes for testing it. When a software is in
development stage, the tests and cases are built accordingly. This helps the developers to see any errors of server or
network etc. Same goes for any other stage of software such as production stage in which you evolve and upgrade
those tests cases. The area for covering your tests should be as wide as possible. It should cover every little
possibility of the failure so that the software is built of premium quality and feedback team receives minimum
tickets.

With this section, we conclude this tutorial here. Next in this course we will introduce you to the software postman
and will download it on our systems. I hope you will enjoy this course with me.

Page | 24
Download Postman and Install On Windows and MacOS
Download and Install Postman

Since you now know about the application and have become familiar with its working, it's time to install the
application on your system. In this chapter, we will cover How to Download and Install Postman on Windows
Machine.

Postman is available for Windows, Linux, and Mac as a standalone application. You can install the application in two
ways.

• As a Standalone Application.

• As a Chrome Extension

We will be discussing both methods in detail.

You may also go through the recording of the Postman Tutorial where our experts have explained the concepts in
depth.

Download POSTMAN as a Standalone Application

A native application means the application will not be supportive of any particular application on an operating
system. For example if you install an extension from chrome webstore then that application or extension will only run
on chrome and no other browser. A native application is like any software that you install like a game or IDM or any
antivirus for instance. A native application takes the support of just your operating system and not another
application because they are written system specific and not application specific.

1.Go to https://www.getpostman.com/apps

Note: If you are using windows then there is an option for downloading for 32-bit system and 64-bit system. If you
are using 64-bit windows then select x64 and if you are using a 32-bit system then select x86. The default value is
x64.

2. Choose the Operating System on which you want to download PostMan and click on "Download" button.
Since I have got Windows 64-bit machine, I am going to install x64-Windows.

Page | 25
3. Once you download the .exe file, you will need to install the application. Since I am using the Chrome browser, the
downloaded .exe will appear at the bottom left of the browser.

3. Click on the exe file to install it on the system. First, it will install the POSTMAN application.

Page | 26
4. There are no further steps for installing. After completion, it will automatically start opening the PostMan
tool.

5. Once you have the application window up, click on Take me straight to the app. I'll create an account
another time as highlighted. Alternatively, you can sign up with google but it does not matter at present.

If you see this page then you have successfully installed Postman on your system.

Page | 27
Download POSTMAN as a Chrome Extension

1)Go to Chrome WebStore - PostMan Tool and click on Add To Chrome.

2. This will display a pop up to add extension, click on Add app.

Page | 28
3. Now it will automatically open a Chrome Apps page, where it will display all the installed apps on your
chrome browser. Simply click on the PostMan application.

4. It will take a few seconds to start, hold on till then :)

5. Once done, you would see the PostMan application registration page. As mentioned above, we will ignore
registration as of now but not to avoid it, *Registration has its own benefits, as it always stores your data
and can be accessed from different machines and locations. *But we will cover that later.

Page | 29
Why to prefer PostMan as a Stand Alone application

Although Postman was introduced first as a chrome application and was powerful earlier on, we highly recommend
downloading postman as an application for your operative system(native application) rather than as an extension for
chrome.

There are two main reasons for this.

• First of all, postman as an application for chrome does not support all the features that the native app has.
For example, a proxy cannot be captured in the chrome app. You need to install another extension
called postman interceptor in order to work the proxy through the browser. A proxy server acts as an
intermediary that captures the requests that you send through your browser to the server. Requests are
anything like any web address any search query or anything that asks for a response from server. For
example, when you hit "Search" in google after writing something in the search bar, it is an API request or
you type www.google.co.in in the address bar, it is an API request. After installing the postman interceptor
only you can capture the requests that you send. Moreover, Postman features fewer menu options in its
chrome app, only those which adhere to the chrome standards. Therefore you won't be able to enjoy every
feature of Postman while using it as a chrome application.

• The second reason is the main concern for us to not recommend you, download postman, for chrome. As
stated on the Postman website, Postman builders have stopped the support for the chrome application. This
in simple terms means that from January 2018 onwards, there will be no updates, no bug fixes, no
improvements in the chrome application. The app that is currently available on the web-store is the final
application. Moreover, if you are stuck on any issue, there will be no one to resolve it from Postman. This step

Page | 30
is taken by Postman after Google announced that it will be ending support for the Chrome apps for Windows,
Linux and Mac.

As it can be seen in the below image taken from the postman website, the last update for the Chrome app was on 18
Oct, 2017. So, it is better that you install the Standalone application and the same will be used by us for this course.

In the next chapter, we will run through some basics and terminologies about the Postman.

Postman Navigation
Postman Navigation

Now that we have installed Postman on our system, we will navigate through the UI of Postman in this Chapter. We
will become familiar with the terminologies and features that Postman offers.
Page | 31
You may also go through the recording of the Postman Tutorial where our experts have explained the concepts in
depth.

Postman navigation can be divided into four UI structures as shown below.

1. Sidebar section

• History

• Collections

2. Header section

• New

• Import

• Interceptor

• Sync

3. Builder section: These items will help users to create a new Request. We will learn about these items in detail
in the coming chapters

• Tabs

• HTTP Method type

• URL bar

• Header's list

4. Response section: It is filled only when invoking a REST request. This section will be populated with the
details of the received Response. We will learn more about it in the coming chapters. Now let us see
individual sections in detail.

PostMan - Left Sidebar Section

The sidebar is a very important part of the Postman. The sidebar has two main parts or tabs which
are History and Collections.

Page | 32
History Tab

Postman records a history of your API request just like any other web browser automatically. As soon as you invoke a
REST request, it is saved in the history and can be seen below the History Tab. It comes in handy when you have to
search for some particular request that you entered in the past without entering again.

Collections

The concept of grouping requests is called Collections and each Collection is displayed under the Collection Tab. As
shown in the image below. A collection in Postman can be imagined similar to a folder in your system. You create a
folder, for example, movies, and keep movies in it so that you know where all your movies are. Similarly in Postman,
we save the similar kind of requests under some collection name (that we define) and when we open any collection
we get all the Requests under that heading, As shown in the below image

Postman - Header Section

The below image shows just the Header of the Postman application.

The header has the following items

New

Page | 33
Choosing this option will let you choose what "new" you want to start. For example, a collection would open the
panel where you can enter a new collection to start and its corresponding requests. Selecting "request" in New will
open the request panel where you can enter and save the requests into the collection of your choice. A new option
lets you create the following:

• Request

• Collection

• Environment

• Documentation

• Mock Server

• Monitor

Import

Import option lets you import files of different formats. Importing means choosing the files located in your system or
through a link and running it through Postman. As can be seen from the image it allows you to import a Postman
Collection, Environment, Curl command, etc. Importing a collection is the most common among all.

Interceptor
Page | 34
Recall we learned that if you are installing the application from chrome then a separate interceptor is required for
the proxy server. This interceptor is inbuilt in the native app. You can set a proxy server here to capture all the API
requests that you send through your browser. A proxy server can be used to capture all the requests that you send
through your browser or from your phone or any other system.

Sync

Sync option is for synchronizing the API requests that you have sent on any machine to the Postman cloud. When
you are working in Postman and making changes or sending requests, if you Sync is on, it will automatically be saved
in your Postman's cloud storage. This way you can have them saved and whenever you sign in on a different
machine to use Postman, they will automatically appear. This feature requires you to sign in (If you did not during
the installation part).

Postman - Builder Section

A builder part of the Postman is basically what a CPU is to a computer. It is the main part that controls all the
functionalities and methods to be incorporated inside the API.

A builder part has the following main parts:

• Request Type:

• Endpoint Address Bar:

• Params: This option let the user define different Query Parameters for the request.

Request Type

This is the request type method for the API. It indicates the type of HTTP Request that has been sent. There are
different kinds of requests which we will discuss as we proceed further, but just to know, there are four main types
of requests namely GET, POST. PUT and DELETE.

Endpoint Address Bar

This is the box, besides the request type option, to enter the EndPoint (API). It acts just like a browser with a similar
interface for the New tab. We enter our required endpoint into the bar which is our main URL.

Params

Params are the parameter option that allows us to write the parameters of the URL. The parameters are embedded
into a URL and are very important to get the desired result. They also help us in getting efficient usage of the
memory and bandwidth. This will be discussed in a complete chapter later on.

Authorization

Page | 35
The authorization process verifies whether you have permission to access the data you want from the server. Not all
data is available for everyone inside a company, so there lies the solution as Authorization. With the authorization,
the server first checks whether the data you are asking for can be shown to you. If it can be, you get the desired
response.

Header

A header in the HTTP request or response is the additional information that is needed to be conveyed between the
client-server. HTTP headers are mainly intended for the communication between the server and client in both
directions.

Postman - Response Section

A response box is a box that shows the response from the server that we receive after requesting through API. A
response box has many options in it, which won't be feasible to explain here in this chapter. In the coming chapters
you will learn about the response, although if you want you can visit the chapter here.

In the next chapter, we will start our first steps in Postman.

Create New Request in Postman


How to Create New Request in Postman?

Now, since we have installed Postman and have become familiar with the interface, it's time to start our first steps
on Postman for which Postman is actually used for. To start with this tutorial, we will start with the Header part of
the Postman and follow the steps.

You may also go through the recording of the Postman Tutorial where our experts have explained the concepts in
depth.

Create New Request in Postman

1. Click on the NEW option in the header part.

Page | 36
2. Click on Request.

3. Enter a meaningful Request Name, like First Api we are using. You can also use the description about the API
to remember later about what that API did for other teammates and yourself, but it's optional and we won't
be using that in this tutorial.

Page | 37
4. Enter a meaningful Collection name in the bottom panel, like First Collec we are using, and select +Create
Collection as shown. Press Save.

5. Select Collections tab in the sidebar, then you will notice all the collections folders, select First Collec and
then select First Api under the First Collec tab.

6. Enter www.google.com in the Address Bar and press Send.

7. Press Save if you wish to overwrite "First Api" or press the dropdown as shown and Save as a new request.

Page | 38
The Save As option opens the same panel which opened through New Request at the start of this tutorial. It gives
the option to enter the name and associate the request to some collection.

This way you have created a Request and saved it under the desired collection. In the next tutorial, we will send our
first GET request.

GET Requests in Postman


Since we have now walked through Postman and seen How to Create and Save a new Request in postman, it's time
to get our hands on the first GET Request in Postman. When we request from a client machine (User) to a server
machine, we follow an architecture and HTTP Protocol. I suggest you go through the below tutorials to establish a
nice understanding of HTTP Protocol, Request & Response.

Assuming you are now familiar with the HTTP protocols and architecture, we will now talk about one specific type of
request which is a GET request. A GET request is used to get the information from the server and does not have any
side effects on the server. Side-effects mean there is no updation/deletion/addition of data on the server when you
are making this type of request, you just request from the server and the server responds to the request.

A GET request has all its information inside the URL, and since URL is visible all the time, it is advisable not to use this
type of request while you send some sensitive information such as passwords. For example, when you press search
after writing anything in the search box of google.com, you actually go for a GET request because there is no sensitive
information and you are just requesting the page with search results, you notice the same search string in URL.

You may also go through the recording of the Postman Tutorial where our experts have explained the concepts in
depth.

In this image, as you can see, there is a drop-down button which has different types of request types according to
the API need. As of now do not worry about all of these different HTTP Requests, as we will cover each of these in
this Postman Tutorial series. But for now, just focus on the GET Request.

1. Select GET from the list of request types.

2. Enter www.google.com in the address bar as written in the above image and Press Send. Now, look at
the Status Code.

Page | 39
Different status codes have different meanings and it does not matter whether it is a GEt request or any other type
of request. In this scenario, we have status code 200 OK which means that EndPoint is correct and it has returned
the desired results. We will show some more status codes later.

The colorful text inside the box below is the Response from the server. If you observe closely inside the response box
you will see the page code has been sent to us. The above tab says Body. Body means you have selected to view the
response body which is been shown inside the box. In Body, you will see three options.

• Pretty: In this code will be shown in a colorful manner with different keywords colored differently and will be
indented for some of the formats for good reading.

• Raw: Same as pretty part with no colors and in single lines.

• Preview: This shows the preview of the page that has been sent. Don't worry about the google doodle if it
has not been loaded properly. Try any other website by yourself.

A response is a more detailed topic than it needs to be explained in this chapter. We will be explaining the response
completely in the next chapter.

Response in Postman
In the last tutorial we learnt about Get Request in Postman. In this tutorial we will understand how to deal
with Response in Postman. It will be beneficial if you understand the underlying details of an HTTP Request and
an HTTP Response.

What is Response?

A Response is a message that is received by the server in return to a Request that we send. When we request
something, the server acts upon the Request and sends back a packet of the requested information. A response
depends on the request mainly. Every request has a different kind of response and it is very important that we
extract useful information from all of the responses. Postman has a beautiful interface for response and is very user-
friendly. We can see a lot of information in the Postman for any response without doing much effort, or any if I
might say.

Page | 40
You may also go through the recording of the Postman Tutorial where our experts have explained the concepts in
depth.

Understanding Response in Postman

Talking about Response in Postman, the Response user interface contains lots of different things. We will deal with
them in detail in this tutorial. The user interface has the following information blocks

• Response Status and Information

• Response Body

• Response Cookies

• Response Header

Let's start by getting a response for www.google.com which looks like this:

Response Status and Information

Status Code :

A status code tells you the status of the request. There can be a lot of mistakes in the request and without looking at
the status code, we might not always get what went wrong to our request. Sometimes, there can be a typing mistake
in the URL or there can be a problem at the server-side, status code help us know about what went wrong (if
something went wrong). There are different status codes and each of them has a different meaning.

You can learn about the complete list of status code here.

Status code 200 OK means that the request was correct and the desired response has been sent to the client. Now,
change the URL to http://restapi.demoqa.com/utilities/weatherfull/city/hyderabd . Press Send and see the status
code now.

Page | 41
It says 400 BAD REQUEST. It is so because we have changed the name of the city from Hyderabad to Hyderabad.
This means the request was not correct, hence the bad request response. Similarly, you can see other status codes
also for different requests.

Time

Time is the duration which the response took after we sent the request and received the response. This is very
important sometimes because many projects have Service Level Agreements(SLA) for the time it should take a web
service to return a response, this time can be a used to determine the SLA of the web service endpoint.

NOTE: The time given here is not the actual time that the request will take. It is just approximate but almost what it
would be because there are a lot of things that Postman do after getting a response such as formatting and dividing
Headers and cookies separately. As the additional work by Postman can be roughly considered as a constant time
(WebServiceTime + Constant processing time by Postman). Therefore, it is an approximate of the time and is
proportional to what the actual time will be. So you can consider this as actual time as well.

Size

Size is just the response size when it will be saved inside the memory. This response size is the size of complete
response and headers and cookies and everything that has been sent along with the response.

NOTE: The response size that is shown in the Postman is approximate response size and not the exact size.

Response Body

A body depicts the body of the response, which is the main response content, that has been sent from the server. In
this case as you can see it is a web page code being sent to us as a response. Now, there lie three ways ahead of us
to look at this response:

Pretty

Pretty is a prettier version of the content being sent. The content is prettier as it is more readable. It has coloured
keywords and different colours have different meanings. This makes a code more readable and look nicer. This
formatting is done by Postman itself after getting the code.

Raw

Page | 42
Once you click on Preview you will get just the plain view of the content, as received from the server. It is just a raw
version of the code without any colorful keywords. By looking at this code you might get why the other code is called
"Pretty".

Preview

Preview of the code will show you the preview of the page, had the page been run inside a browser. Click on preview
and you will see the exact page as you would have seen inside a browser. So this would let you know the response
preview without visiting the browser.

Format Type

As discussed above, a request has a defined response to it as defined by the Content-Type header. That response
can be in any format. For example, in this case we have the response as a HTML code file.

Postman is smart enough to detect the response type and show you in the desired format, but sometimes Postman
can also make a mistake. For example, use http://restapi.demoqa.com/utilities/weatherfull/city/hyderabad to get
a response.

You will see that we have received a status code 200 and still there is no response. This is because Postman has
failed to recognize the format of the response and is expecting a HTML file as seen in the dropdown.

Select Text in dropdown and you will be able to see the response now.

Page | 43
Sometimes, the server sends the response in two or more different formats. The type of response will be visible to
its corresponding format type.

Note: Content-Type header defines the format of the response. For e.g. the Content-Type header may say that the
response is JSON, however, the content being sent is XML or a malformed JSON. In that case Postman will not be able
to do much. Take it as an exercise to understand why Postman is not able to understand the format of response
returned by http://restapi.demoqa.com/utilities/weatherfull/city/hyderabad

Copy Response

The icon with two rectangles that you see in the corner is used for copying the complete response to the clipboard
which is very handy to send the response to your teammates or using afterwards.

Cookie

Cookies are the small files which are related to the server files (website pages). Once you visit a website for the first
time, a cookie is downloaded on the client's machine. This cookie contains the information which can be used by the
same website when you visit again. This helps the website to get you the specific response and specific information
based on your last visit. In postman we can clearly see the cookies that have been sent from the server as a
response. This makes it easy for the client to see what cookies are being saved inside his browser. We cannot
manipulate this cookies since they are sent from server, Postman is used just to separate it from the response and
have a clear view.

Header

Headers in an HTTP request or response is the additional information that is transferred to the user or the server. In
postman, the headers can be seen in the Headers tab.

Page | 44
Once you click on header you can see different information such as below. Although, every entry in the Headers tab
is a header item we will just take a look at the most important ones.

• Content-Type : This is the content type of the response. In the above example when we used
www.google.com the content type is given as text/HTML because the response is being sent in the HTML
which is one of the options.

• Date : This option shows the date, day and time of the response along with the time zone.

• Server : This option tells the name of the server which has responded to the request. In the above example,
the server name is shown as gws which corresponds to Google Web Server.

• Cookie expire time : As the name suggests, this option tells the expire time of the cookie that has been sent
along with the response.

Request Parameters in Postman


What are Parameters in Request?

Request Parameters are part of the URL which is used to send additional data to the Server. Let us analyze a simple
URL:

https://www.bing.com/search?q=ToolsQA

In this URL Request parameter is represented by the "q=ToolsQA" part of the URL. Request parameter starts with a
question mark (?). Request parameters follow "Key=Value" data format. In our example "q" is the Key
and "ToolsQA" is the value. The server reads the Request parameter from the URL and sends a Response based on
the Request Parameter. In our example, Bing will return search results for ToolsQA. If you change the Value
from ToolsQA to DemoQA, you will get results for DemoQA instead of ToolsQA. This means that the Server reads the
Request parameter and responds based on that.

In simpler words, let us say I designed a page that can show you the student list of a particular class. Now, the list will
depend on the class you select, which will be passed in the URL as a parameter while the page I designed will be the
same for every class. I don't have to design many pages as many as there are classes. This way we improve the
efficiency and usage at both levels.

Parameters can be passed in GET Request, if you are not sure how to do a GET Request using Postman, please take a
look at the previous article How to make a GET Request. Since now you know how to make a GET request, we will
move ahead with sending parameters in a GET request.

You may also go through the recording of the Postman Tutorial where our experts have explained the concepts in
depth.
Page | 45
Before talking about Parameters and understanding them clearly, we will send the URL to our browser.

1. Go to your browser and write www.google.com in your address bar

2. You will see the response page from Google. Type ToolsQA in the search bar and press Google Search.

Now you need to understand here that the page which shows the results will remain the same just the results will
differ according to the search. You just now searched for ToolsQA, this serves as a parameter in the URL to tell the
server that we need the results of the ToolsQA specifically. The server responds according to the search parameter.

A URL consists of many parameters such as source id and encoding format etc. See the URL below and you will
see &q=ToolsQA which is added in the URL to tell the server.

Page | 46
Note: here "q" is the key represents query and ToolsQA is the value of the key or search term for the query.

Now, we will try to achieve the same results through Postman.

Request Parameters in Postman

1.Just prepare a GET Request in Postman with the URL www.google.com/search and then click on Params.

2. Write the following things written under Key-Value pair as shown. Again q stands for query here and
ToolsQA is the search term. Now press Send.

3. Look at the preview, you would see that instead of the google home page we have received a response for a
specific search query which is ToolsQA. Instead of ToolsQA you could write anything and receive its
response. This indicates that we have passed some information (Parameters) about the result we wish to
see.

NOTE: As discussed above, you can see that different search queries give different results but the page design
remains the same, just the content differs.

Multiple Parameters

You can also use multiple parameters inside a single query. As we discussed above while sending the search query
as ToolsQA, there are many parameters that are sent in the URL. ToolsQA was for the results that were to be shown,

Page | 47
another parameter such as encoding format is also used to tell the server in which format can the result be encoded
and sent to the client. In the above example, the default encoding format used is UTF-8.

See the above image and focus on just the URL sent to the server

In the above URL wherever you see & it must be succeeded by a parameter such as &ie=UTF-8 means ie is a key
parameter with a value UTF-8. You can write each of the parameters that you see above in the postman and send a
request with multiple parameters.

These parameters are not for our users to study in detail. Even if you change the parameters, the changes reflected
will not be seen on the page and you will still get the same response as before because all these parameters are for
internal activities in the server such as logging the submission.

Separating parameters from URL

If you are wondering how to separate a given complete URL with its parameters to use in Postman then Postman has
it sorted out for you. You do not need to worry about the parameters in a URL. You can simply paste the URL and
Postman will fill the parameters itself.

For example, copy and paste this URL inside your postman like shown
below https://www.google.co.in/search?q=toolsqa&oq=toolsqa&aqs=chrome..69i57j69i60l5.2885j0j4&sourceid=c
hrome&ie=UTF-8

Now click on Params and you can see that everything is sorted out itself and the parameters are as in the above
image (more or less).

Copy parameters to another Postman Request

Another interesting feature about Params is that Postman removes the headache of remembering and entering the
same parameters again and again to every query, instead it lets you enter once and forget about entering the same

Page | 48
parameters again. For example, let's say you have to run the same query that we just run but with a few fewer
parameters. For achieving the same,

1. Click on Bulk Edit, you will see the list of all parameters

2. Copy everything

3. Open a new tab and write your URL which is www.google.com/search in this case

4. Click on Params, then Bulk Edit

5. Paste everything you copied in the editor and click on Key-Value edit

Here you will see every parameter has been adjusted automatically to the new request.

Page | 49
This makes Postman really very efficient while using the parameter option and leaves us out of the context of its
complexity. A parameter is a very important part of a URL and readers are recommended to observe the different
parameters in a URL for better learning and understanding, whereas this was all about parameters usage inside
Postman. Next, we will see about the response in Postman.

POST Request using Postman


POST Request using Postman

In the previous tutorials, we have learned about how to send a GET Request and we also learned about the Request
Parameters. From our Rest basics we already know what an HTTP Request and HTTP Response is.If you have not
read these two tutorials yet, please do that before proceeding. In this chapter, we will focus on another type of
request method which is POST Request in Postman.

What is a POST Request?

A POST is an HTTP Verb similar to a GET request, this specifies that a client is posting data on the given Endpoint.
A POST request is a method that is used when we need to send some additional information inside the body of the
request to the server. When we send a POST request we generally intend to have some modification at the server
such as updation, deletion, or addition. One of the classic example of a POST request is the Login page. When you
first Sign Up for anything, let's say Facebook, you send your personal information such as a password to the
server. The server creates a new account with the same details and that account is added permanently on the
Facebook server. You just created a new resource on to the server. POST requests are very popular and are mostly
used whenever you are sending some sensitive information such as submitting a form or sending sensitive
information to the server.

In this tutorial, we will explore different features of POST Requests and how we can create them in Postman. Before
we will try to use an example to get a clear idea about a POST Request.

POST Request in Postman

Every REST endpoint has its own HTTP verb associated with it. If an endpoint specifies that it should be called using
the POST HTTP verb, then clients are bound to call the Endpoint with POST HTTP verb only. Let's first check what
happens when we request the GET method instead of the POST method for a POST Endpoint. Also to check what
happens when we do POST Request without Body.

GET Request on POST Endpoint

1. Use the API http://restapi.demoqa.com/customer/register (This API is used for registering a new
customer) in the Postman endpoint bar and press Send. Make sure that GET is selected in the Method type
dropdown.

Page | 50
2. See the HTTP status code, it will be 405 Method not allowed. Which means that we are hitting the endpoint
with incorrect method type. The below image shows the details.

3. See the response below under the Body tab and focus on fault error.

It means that the method type we used is not valid and another method type is expected. So we will try to change
that and see if we get the correct response.

POST Request without Body

1. Change the method type to POST and press SEND

Page | 51
2. Now, look at the Response Body and Response Status code.

Fault Invalid Post Request means that the post data that we entered is not valid. Recall that we add the information
inside the body of the request, so we need to enter something into the request body and see if that format matches
the format expected. Also, you can see the status code which says 400 BAD Request. It means that the request
parameters are not matching the server parameters to get a response.

Post Request in Postman

1. Now let us add a Request Body to our POST request. Every Endpoint will be documented with what kind of
Method type and the format of the body that it expects. Let us see what body this request expects and how
to add it. For that click on the Body tab.

2. Click on raw and select format type as JSON, since we have to send the incorrect format that the server
expects.

Page | 52
3. This endpoint expects a Json body which contains the details of the new user. Below is a sample Json body.
Copy and Paste the following in the body tab of Postman.

* “FirstName”: “value”*

* “LastName : “value”,*

“UserName : “value”,

“Password”: “value”,

“Email”: “Value”

Change the attribute value to any value you want (take reference from the below image).

4. Press Send and see the Response Body and Response Status.

The error Fault User Already Exits means that in the database, a similar entry has already been created by you or
anyone else earlier. Whereas if you see that the Response Status is 200 OK, which means that server accepted the
request and sent back a successful response. We can also infer from this that the response body was correct and the
server was able to interpret the response body. Now in this API Request, Email and Username should be unique. So
you can change those values (anyone will also work).

If the values are unique, you will get this response

Page | 53
Operation completed successfully means that your entry has been created successfully in the database.

So, by this example, it is clear that whenever we need to send a POST request, it should be accompanied by the
Body. The body should be in the correct format and with the correct keys to get a correct response from the server.
Now, we will learn in detail about every feature of Post request in Postman.

Different ways to send the data in a POST Request in Postman

As we discussed earlier, sending a POST request means sending a request with the data wrapped inside the body of
the request. There can be different types of data and similarly, there are different ways of sending data. As you will
follow these steps, you will learn in detail about it.

1. Select the method request type as POST in the builder as shown.

As soon as you select the POST request type in Postman you will see that the option Body is enabled which has
different options to send the data inside the body. These options are:

• Form-data

• X-www-form-urlencoded

• Raw

• Binary

Form Data

Page | 54
Form data as the name suggests is used to send the data that you are wrapping inside the form like the details you
enter when you fill out a form. These details are sent by writing them as KEY-VALUE pairs where the key is the
"name" of the entry you are sending and value is its value. The following steps will make it clear.

1.Select form-data

2. Add the following KEY-VALUE pair

• First name: Harish

• Last name: Rajora

Here, the first name in the field of some form (text field here) that is needed to be entered and Harish is its value i.e.
the value the user has entered. Similarly goes for Last name id.

x-www-form-urlencoded

Form data and x-www-form-urlencoded are very similar. They both are used for almost the same purposes. But the
difference between the form data and x-www-form-urlencoded is that the URL will be encoded when sent
through x-www-form-urlencoded. Encoded means the data which is sent will be encoded to different characters so
that it is unrecognizable even if it is under attack.

Raw

Raw is the most used part or option while sending the body in the POST method. It is important from the point of
view of Postman. Raw means the body message is shown as a stream of bits representing the request body. These
bits will be interpreted as a string server.

1. Click on the dropdown besides binary and there can be seen all the options in which you can send the
request

2. Click on JSON(application/json)

Page | 55
3. In the editor below copy and paste this

"first name": "Harish",

"last name": "Rajora"

This is the same data that was sent previously with form-data but instead it is now sent with the JSON format.

Binary

Binary is designed to send the information in a format that cannot be entered manually. Since everything in a
computer is converted to binary, we use these options which cannot be written manually such as an image, a file,
etc. To use this option

1. Click on binary, a CHOOSE FILES option will be available

2. Choose any file, such as an image file.

Note: If you wish to send to the server some data along with the file then it can also be done in the form-data.

Click on the form-data

Page | 56
Enter file as a key

and you will see a hidden drop-down that says Text as default. You can choose any file format and then select the file
from the system.

Always remember what your server is expecting. You cannot send another format than what your server expects,
otherwise, there will be no response or incorrect response which can obviously be seen by the status code of the
response. So now, we have learned about the POST method and how to use it in Postman. We will move on to the
next tutorial now which is Collections.

What is REST?
The world wide web has become too complex today. With hundreds and thousands of electronic media talking to
each other, the process of communication has become too complex and heavy on computation for sure. Such
scenarios call for something that can ease out the communication and keep the coding complexity to a minimum as
well. That something is the focus of this post and is termed as REST.

REST, or REpresentational State Transfer, is an architectural style and provides standards between the systems on
the web. Popularly, RESTful systems use the REST style to communicate with each other. So in many places, you
might see "RESTful" over the internet and it means the same thing. In this article, we dwell in more details about
REST basics and will cover the following topics in this article.

• What is REST - Representational State Transfer?

• What are Clients and Resources?

• Guiding principles or constraints of REST

o Uniform interface

o Client-server separation

o Stateless

o Layered system

o Cacheable

o Code-on-demand

What is REST - Representational State Transfer?

REST (REpresentational State Transfer) was first presented in the year 2000 by Roy Fielding as an architectural style
for distributed hypermedia systems. REST-compliant or RESTful systems, are "stateless" (discussed later in this

Page | 57
article) and separate a client and a server. A web application developed using REST (RESTful web
application) exposes the data or information about its resources which can be anything that the developer wants.
This allows the client using this application to take action on the resources. For example, using information exposed
to users, clients can create a new user.

As another example, suppose we have a pet store and the information related to all pets in the store is stored on the
server. If we want information related to a pet (let's say pet with id=0) then we will access the appropriate URL of
the pet store in the browser (Here the browser will be the client). An example URL can
be "https://demoqa.com/BookStore/v1/Books".

The above interface looks as shown below:

All the methods (coloured buttons) shown in the above screenshot correspond to REST APIs that are executed with
the click of a button. Please note that this is a demo website and therefore the APIs are so explicit on the screen. In
general, all this is done in the back-end and the client is not shown any of this information. Coming back, when we
click the "GET" button (/Books), we will get the response in JSON format that will show us the details of the
particular book. This response is shown below:

Note: When we click on the "GET" button, in the browser we see the link changes
to "https://demoqa.com/BookStore/v1/Books".

We will discuss all the methods shown above (in form of buttons) in our subsequent articles.

Representation of REST flow

Now let us depict the actual REST data transfer in the above example in the diagram below.

Page | 58
As the above diagram shows, the API works as a medium of communication between a database (that is a part of a
server) and a client. When a client sends data through APIs, it goes to the database, do the appropriate
operation (such as add, delete, modify etc.) and return the response data that contains response code, header files,
cookie info etc.

We can summarise the REST characteristics and the working in the above diagram as follows:

• A client access data from the server passed by REST. This can either be through authorized access or without
following any strict guideline.

• As we can see, the application developed using REST is an interactive application and mostly it uses web
services. In this case, the web service follows RESTful guidelines and fulfils the constraints of REST that are
discussed later in this article.

• A web service using REST provides web resources in textual format and allows them to be read and edited
using a predefined set of operations.

REST is a way to access a web service and is often viewed as an alternative to SOAP (Simple Object Access Protocol).

In a RESTFul application, we have entities namely client and resource which are used commonly. Let us discuss them
briefly next.

What are Clients and Resources?

A client can be a software or a person or a system using the APIs to access data from another application server. For
example, a developer might access Facebook APIs to embed a live post in their own website. The developer program
will call the Facebook API through a browser. So in this case, the browser acts as a client that is calling the Facebook
APIs.

If we visualize this system using the REST diagram above, the client or browser will connect to Facebook-Server over
REST API and then get the information required to render it on the screen.

As another example, suppose I have an application "myHealthApp". I want data on the Covid-19 pandemic from a
city, Pune, for example. To achieve this, I will develop APIs or methods, such as, "Corona API" using which I can
request the data from Pune Municipal Council (PMC). This is done using myHealthApp. This means using
myHealthApp which acts as a client, I will make a request for data using Corona API (say getCoronaData method to
be more specific) through the browser ( for example, https://myHealthApp/getCoronaData). This getCoronaData
method will in turn connect to PMC servers and fetch the required data as a JSON response (or any other
format). On the client side, I can take that data and perform various operations on it. This is the use of APIs.

What Is A Resource in REST?

Any smaller unit that can be transformed and addressed through a URL and HTTP method is considered a resource.
This resource makes changes to the database. For one application, you may have a lot of resources with all of them
assigned a particular task. For example, an online book store may have a resource as a table of the database. A
resource in a REST architecture is anything that a client has access to and can modify or update.

Page | 59
In a way, you can say that a resource is any object for which we need information from API. So in the above example
about Facebook, a resource can be a post, page, or user account. In the example of Corona API, resources are all the
details on Corona like Corona data, pages on treatment, vaccination, etc.

Guiding principles or constraints of REST

For an API to be RESTful, it has to fulfil or adhere to the following guiding principles or constraints defined by REST.

Uniform interface

The uniform interface principle has the following parts that an API has to follow:

1. The request to the server needs to have a resource identifier.

2. The server returns the response and includes information such that the client can modify or edit the resource.

3. The request sent through the API contains the information that the server needs to execute the request. Each
response returned by the server also contains all the information so that client understands the response.

4. Hypermedia as the engine of application state. The application means the web application that is running on
the server. Hypermedia is the hyperlinks or simple links included in the response. So the server basically
informs the client about the ways to change the application web.

Client-server separation

The interaction between the client and the server is independent and is only in the form of requests. The client
initiates a request and the server sends the responses. The response is a reaction to the request. So all server does is
wait to receive requests from the client. It never sends out information about the resources to the client on its own.
For more details on client-server refer to our tutorial, Client-server Architecture.

Stateless

The word "stateless" means the server does not keep track of the user who uses the API. So when a new request
comes in, the server will not know if the same user has sent a GET request in the past for the same resource. It
doesn't remember the resources requested by the user earlier. For example, HTTP is a stateless protocol. HTTP
server does not keep track of any state of information passed to and fro. Hence at any given time, a client can send a
valid command, and the server will not relate or keep track of any previous similar commands.

Hence each request regardless of the other requests made by the user will contain all the data needed by the server
to execute the request and send a response.

Layered system

A layered system provides a hierarchical structure between a client and a server. There can be a lot of intermediaries
between the client and the server working along with REST API without the client's notice. Our clients think there is a
direct connection to the server. We then take advantage of it to improve our architecture and bring down our
distributed system complexity. These intermediate elements provide a security layer, load-balancing layer, and other
functionality to the system. The only guideline is that the presence of these intermediate layers should not affect the
request or response.

Note: The abstraction of layers does not let one layer be aware of the presence of another layer.

Cacheable

The server data received in the response contains information regarding whether the data is cacheable or not. If the
data is cacheable, it will contain some kind of version number that makes caching possible. The client will know
which version of the data it has got from the previous response. This way client can avoid requesting repeated data.
Cacheable data (and therefore version number) also helps the client to know the expiration of version data and the
requirement of a new request to fetch the latest data.

Page | 60
Code-on-demand

This particular constraint "Code on demand" is optional and without fulfilling it we can have a RESTful API.

The client can send a request to the server asking for the code and then the server will respond with some code in
the form of a script or some other entity. For example, servers can extend the client functionality by downloading
and executing pre-compiled code like an applet or a client-side script like JavaScript. So when we click on any video
on Facebook, Facebook will run a precompiled or any third-party software to run that video.

Once an API fulfils the above constraints we discussed, we can say it is a RESTful API.

What is Rest Api?


In our last article, we discussed what is REST and the various constraints that should be adhered to by a RESTful
application. All our knowledge gathered regarding the REST architecture can be applied in performing operations
with REST API. In this article, we will cover the same with the following topics in the highlight.

• What is REST API?

• Why use REST API?

• Methods of REST API

What is REST API?

An API (Application Programming Interface) conforming to the REST architectural style or REST standards is known as
a "REST API". A Rest API facilitates interaction between the client and RESTful web services*( server)* to get the
required information. They can be used for a variety of purposes by interacting with the system. These may include
specific actions such as retrieving the location of a particular city or data updation such as registering a new user. API
developers use REST standards in a variety of ways to develop REST APIs. The following diagram shows a general
REST API functionality.

As shown in the above diagram, REST API sits in the middle layer to the database and the presentation layer i.e. the
interactive systems. The other applications (shown as the top layer) will call the REST API that has centralized core
logic in one place. The applications call REST APIs to access the desired data. For example, if we try to hard code

Page | 61
everything, we need to code for each action on the website. Retrieving book by book serial number is an action that
may need to run through the middle layer and then the database. It can take a lot of time depending on the size of
the database and website. With RESTful APIs, the process becomes much faster as they are lightweight. So instead
of writing separate code and logic for each application, we write REST APIs accessible by any application.

What happens when a client makes a request through the RESTful API?

When a client makes a specific request, RESTful API transfers a state representation of the resource to the requester
or endpoint. The format of this representation is one of several formats like HTTP: JSON (Javascript Object
Notation), HTML, XLT, Python, PHP, or plain text. The most popular format generally used nowadays is JSON since it
is easy to read and is very lightweight.

Headers and parameters also play an important role in the HTTP methods of a RESTful API HTTP request. They
contain important identifier information regarding the request's uniform resource identifier (URI), metadata,
authorization, caching, cookies, etc. These request and response headers have their own HTTP connection and status
code information.

Next, let us move on to why we use REST APIs.

Why use REST API?

We mainly use REST API for the following reasons:

1. As we have discussed earlier, the REST API creates an object and transmits the object values in response to
the client's request. The REST API breaks down this transaction into smaller modules wherein each module
addresses a specific part of the transaction. This breaking down of transactions into smaller modules requires
lots of effort but also provides more flexibility for the user.

2. The REST API has strict criteria to conform to. We have already seen the guiding principles (constraints) for an
application to be RESTAssured in our earlier tutorials of What is REST and Rest Architectural Element. This
strict adherence results in efficient REST APIs after their development. Also, we can implement this set of
guidelines as needed.

3. The REST APIs are considered easier than other protocols like SOAP (Simple Object Access Protocol) that have
more specific requirements like built-in security, transaction compliance, XML messaging, etc. All these
requirements make these protocols slower and heavier.

4. The REST applications (and APIs) are more lightweight, have increased scalability, and are more suited for IoT
(Internet Of Things) and mobile app development.

Methods of RESTful API

We perform CRUD Operations when we are working with web technologies and applications. As shown in the below
figure, CRUD stands for Create, Read, Update, Delete. This means using CRUD operations, we can create, read,
update and delete a resource. Generally, we make use of HTTP methods to perform CRUD operations. In the case of
REST API methods, the REST provides these four methods in the form of APIs. Refer to the figure below:

Page | 62
As shown above, POST, GET, PUT and DELETE are the HTTP methods used for CRUD operations. The following table
shows the description of each of these methods as well as an example URL using the swagger
tool https://demoqa.com/swagger/

HTTP
Operation Operation Type Example URL
Method

Get the list curl -X GET "https://demoqa.com/BookStore/v1/Books" -H "accept:


GET Read Only
of books application/json"

curl -X POST "https://demoqa.com/BookStore/v1/Books" -H "accept:


Add list of
POST Non-Idempotent application/json" -H "Content-Type: application/json" -d "{ "userId":
books
"toolsqa_test", "collectionOfIsbns": [ { "isbn": "9781449325862" } ]}"

Replace
curl -X PUT "https://demoqa.com/BookStore/v1/Books/9781449325889"
ISBN object
PUT N/A -H "accept: application/json" -H "Content-Type: application/json" -d "{
with given
"userId": "toolsqa_test", "isbn": "9781449325862"}"
ISBN

Idempotent:
Same results
Delete book curl -X DELETE "https://demoqa.com/BookStore/v1/Book" -H "accept:
irrespective of
DELETE with given application/json" -H "Content-Type: application/json" -d "{ "isbn":
how many times
ISBN "9781449325862", "userId": "toolsqa_test"}"
the operation is
invoked.

How to test GET operation using REST APIs?

So how do we test these methods in a Swagger tool? Let us see an example of GET operation. Navigate to the
following link: https://demoqa.com/swagger/#/BookStore/BookStoreV1BooksGet

We can see the following REST API for GET book details.

Page | 63
Now let us "execute" the GET operation that "gets book details". When we click this button and execute the API,
the below-given command or GET syntax gets executed:

curl -X GET "https://demoqa.com/BookStore/v1/Books" -H "accept: application/json"

On performing the above operation we get the following response.

In a similar manner, we can perform other operations as well for which we have crafted dedicated posts. In
subsequent articles, we will learn to create a REST API ourselves.

So here are some of the points we should remember for REST API methods.

• GET methods are read-only and safe.

• PUT and DELETE methods are idempotent: the response they return is always the same irrespective of the
times the methods are invoked.

• PUT and POST operation are generally the same except for one difference that POST operation can return
different results whereas PUT is idempotent.

Rest Architectural Elements


In our previous article, we have thoroughly learned about REST services and the set of constraints that bound us to
industry standards. Additionally, we may employ specific architectural elements in our software application to get
the desirable results with optimum performance. These REST architectural elements form the key conceptual
elements of a Restful service. The below representation shows the key architectural elements along with the
constraints in a REST architecture-

Page | 64
In this article, we will focus on these three different classes of the architectural elements identified by REST :

• What are Connectors?

• Components in REST architectural elements.

• What are Data Elements?

o Types of data elements.

What are Connectors?

REST uses connectors that manage communication between the different components. There are five types of
connectors that encapsulate the activities of accessing resources. They also enable transferring of resource
representations. All the communication through the connectors is hidden with clean separation thereby enhancing
the simplicity. There are following REST connector types-

1. Client - It initiates communication by sending requests and consumes the response sent by the server.
Examples are HTTP library, client-side web API like libwww.

2. Server - It listens for connections and gives responses to the requests hence allowing access to its services.
Examples are Web server APIs like Apache API, NSAPI, etc.
Page | 65
3. Cache - It is the third connector type which is located at either the client or server connector. It stores
cacheable responses that can be reused for similar interactions. It saves repeated network communication
when employed at the client connector. Alternatively, at the server connector, it saves the repeated response
generation process. Examples are the browser cache or web caching solutions like the Microsoft Azure CDN.

4. Resolver - It translates the resource identifiers into the network address. You know that most of the URIs
consist of DNS hostname. Now the web browser extracts the hostname from the URI and uses the DNS
resolver to fetch the IP address for the naming authority of the resource. Examples are Microsoft DNS, BIND,
etc.

5. Tunnel - It relays information across the connection boundary like the firewall or gateways. REST components
may switch from active to tunnel behaviour. Hence, allowing the client to directly interact with a remote
server using a protocol like TLS. Examples are SOCKS, HTTP Tunnel, etc.

Components in Rest Architectural Elements

Components in REST architectural elements are the different software that interacts with each other. They act as
end-points connected through connectors and exchanging data elements. There are mainly categorized into four
types as described below-

1. Origin Server - An origin server is designed to consume the incoming requests that modify the value of the
resources of any representation. You may think of it as a container that holds the requested representations
of the resources. It uses a server connector to receive and respond to requests. Web servers like Apache
Tomcat & Microsoft IIS are examples of the origin server.

2. User Agent - A user agent initiates a request at the client end. It uses a client connector to initiate such
requests and becomes the recipient of the response. Web browsers like Mozilla, Chrome, etc are classic
examples of user agents. They act as the starting point of any service requested by the user and render the
response as sent by the servers.

3. Gateway - A gateway is an intermediary imposed by the network. It provides service encapsulation like data
translation(compression), performance enhancement(load balancing), or security enforcement(encryption). It
acts as both the client and the server to facilitate the exchange of requests and responses with possible data
translation. Examples are Squid, NGINX, CGI, etc.

4. Proxy - It is also an intermediary to the requests made by the client for some service or some resources.
Similar to the gateway, it provides an interface for encapsulation of services like load balancing, encryption,
or compression. Examples of proxy are CERN proxy, Netscape proxy, CGI proxy, etc.

What are Data Elements?

The uniform interface between the components of REST architectural style distinguishes it from all other network-
based architectures. It makes all the interactions between the client and the server unified through a fixed set of
operations. Data elements and their state form the key aspect of REST architectural elements. The components
interact by exchanging the representation of the current or desired state of data elements.

Types of data elements

REST identifies six data elements as described below-

Resource

A resource is any addressable information on the server. It is a conceptual mapping to a set of entities and not the
data itself. This mapping can either be static or temporal. A static resource is one that remains unchanged over a
long period of time like a web page address. Alternatively, a temporal resource keeps changing with time, as the
weather information about a city.

Resource Identifier

Page | 66
A resource identifier uniquely identifies a resource also known as URI. The URIs and resources follow a many-to-one
relationship. It means that a resource can have multiple URIs providing differing information about the resource. An
example of resource identifier Bookstore API by ToolsQA. The resource identifier for getting the list of available
books is- https://bookstore.toolsqa.com/BookStore/v1/Books On accessing the above resource identifier you will be
able to see the resources, i.e the list of books present in the database.

Resource Metadata

It describes the different properties of a resource by providing additional information like its location or the alternate
resource identifier. It categorizes the resource and gives information about it.

Representation

Representation is the state of a resource and is data plus the metadata which explains the data. In a real sense, we
do not directly send or receive the resource. Rather, we request and receive the representation of resources. A
representation can either be a document, a file, or even an HTTP message entity. XML and JSON are the most popular
resource representations. In our example of bookstore API, the resource representation is in JSON format.

Representation Metadata

This data element, resource metadata, describes the format type of the response body. This helps in the
interpretation of data at the client end. The representation metadata consists of the different headers used in the
request and response. We have explained all the header types in our previous posts on HTTP request and HTTP
response. But let us still quickly see what all headers are included as representation metadata in our example API.

Page | 67
As can be seen, The resource request defines the content-type as a JSON and also specifies the content-length to set
the limit. The response headers also identify the additional information for the response like the User-Agent,
Connection, Accept-Encoding, etc

Control Data

It defines the purpose of messages exchanged between the client and the server such as the requested action and
response meaning. It also helps parameterize requests and override the connecting elements' default behaviour. For
example, control data can modify the cache behaviour of a request or the response. Additionally, the data
corresponding to a certain condition like the last modification date(If-Modified-Since) or if it matches a certain
parameter(If-Match) can be fetched.

Getting started with Rest Assured


In our previous articles, we have discussed the basics of the REST approach including familiar terms, architectural
elements, etc. Moving one step ahead in this direction, let us go ahead with API testing using REST in this article. The
most popular technology we use for API testing is "Rest Assured". We will cover the following topics related to REST
Assured in this article:

• What is Rest Assured?

• Why do we need it?

• Latest Versions.

• Advantages of Rest Assured.

• Disadvantages of Rest Assured.

What is REST Assured?

Rest-Assured is an open-source Java-based library useful for testing and validating REST APIs or RESTFul Web
Services. It is like a headless (no GUI) client that accesses and tests the REST Web Services. It was developed and
maintained by Johan Haleby with the support of several other contributors.

Rest assured simplifies the testing of REST-based services. It brings out the simplicity of dynamic languages like
Groovy and Ruby that perform API testing in Java. The library supports any HTTP method and also has explicit

Page | 68
support for GET, POST, PUT, DELETE, OPTIONS and HEAD. It also includes specifications and validation like
parameters, headers, cookies, etc. We can also use it to verify and validate the response of the HTTP requests.

Source

Apart from testing JSON-based web services, Rest Assured can also be used to test XML-based web services. We can
also integrate this library with JUnit and TestNG frameworks and write test cases for applications. Further, it can be
integrated well with Maven and its efficient matching techniques produce straightforward results.

Yet another powerful feature of REST assured is its support for XML Path and JSON Path syntax to check specific
elements of the response data similar to using XPath API. For people new to such concepts, please refer to the
following syntax examples.

XPath syntax:

<?xml version="1.0" encoding="UTF-8"?>

<bookstore>

<book>

<title>Freedom In Exile</title>

<price>14.29</price>

</book>

</bookstore>

JSON path syntax:


Page | 69
$['store']['book'][3]['title']

Apart from all the above features, this fantastic library also provides various other features like DSL-like syntax,
Specification Reuse, XPath-Validation, easy file uploads, and all the features that are conducive to automated
testing.

Why do we need Rest Assured?

The above discussion about this java library convinces us that it is a reliable library. But why do we need it or what
are the reasons to use it in our application testing?

Following are the main reasons we need Rest Assured :

1. It is an open-source library and has an active development community making it a great choice for API
automation.

2. Earlier, we had to use dynamic languages like Ruby, Groovy for API testing and it was quite challenging.

3. Validation and testing of REST services are harder in Java. Using REST Assured, it becomes simpler and easier.

4. This library uses Java and therefore it becomes simple to send HTTPS requests with customizations using
basic Java code. Once we know the basics of API and integration testing, automation using Rest Assured
gives good confidence on the backend. Thus we can focus more on front-end testing.

Latest Versions

Following are some of the versions of the Rest Assured library we use generally in applications.

1. io.rest-assured - This is a Java DSL for easy testing of REST services. The last release: 11, December 2020
(4.3.3).

2. com.jayway.restassured - This is a legacy library and used for easy testing of REST services using Java DSL.
Last Release: 4 March 2016.

3. ddf.thirdparty - This is a third-party library. Last Release: 09 April 2021

Advantages of Rest Assured

The following table lists some of the advantages of the library.

SNo Advantages

1 It is open-source and hence free to use.

It is very rich in syntax and ready-made assertions. Rest Assured requires less coding as compared to Apache
2
HTTP Client.

3 The setup of Rest Assured is easy and straightforward.

4 The response is given in JSON or XML format and is easy to parse and validate.

5 It uses inbuilt Hemcrest Matchers for easy extraction of values.

6 Response time is quick as also an assertion of status code.

7 The library has a powerful logging mechanism. Also, we can verify headers, cookies, content type, etc on the fly.

It can easily be integrated with other Java libraries like TestNG, JUnit, etc. We can also integrate it with
8
Selenium-Java and achieve end-to-end automation.

9 It has very good support for various API authentication mechanisms.

Page | 70
SNo Advantages

It supports JsonPath and XmlPath that helps in parsing JSON and XML response. It also has support for the JSON
10
Schema Validation library to verify JSON Schema.

11 Rest Assured can also be integrated with Maven and CICD.

12 It supports multi-part form data

13 Supports Spring Mock MVC, Spring Web Test Client, Scala, and Kotlin.

It follows the BDD (Behavioural Data-Driven) approach and keywords like given() when(), then() which makes
14
code readable and supports clean coding. This feature is available from version 2.0.

15 REST Assured 4.1.2 adds support for Java 13.

Disadvantages of Rest Assured

The library has the following disadvantages.

1. It does not support the testing of SOAP(Simple Object Access Protocol) APIs explicitly.

2. Using this library requires that the user has good Java programming knowledge

3. There is no inbuilt reporting in Rest Assured.

Configure Eclipse with Rest-Assured


In the last tutorial, we went through the concepts of Rest-assured in theory. To start our practical journey, we need
to write code that can send and receive the data with a lot more interesting twists in between. However, the
medium that will help us in our API testing is an integrated development environment (IDE). In our case, we will be
using the popular Eclipse IDE and in this post, we will prepare it for our coding exercises. In other words, we will
configure eclipse with rest-assured for API testing. The index looks as follows:

1. What are the prerequisites to configure Eclipse with Rest Assured?

2. How to download rest-assured jars in Eclipse?

3. Creating a project in Eclipse for rest assured.

4. How to setup rest-assured jars in the class path?

What are the prerequisites to configure Eclipse with Rest Assured?

The first step towards setting up the development environment so that we can test some RESTful APIs is to evaluate
the prerequisites. The following list highlights the required software for setting up Eclipse with rest-assured. Before
proceeding, please make sure they are installed on your system.

• Latest Java version.

• Working Eclipse IDE.

• TestNG setup.

If any of the above is not present on the system, then we have to follow the links given below :

1. Set up Java

2. Setting up Eclipse

3. Set up TestNg

Page | 71
Once the prerequisites are up and running we can proceed with the rest assured set up on Eclipse.

How to download rest-assured jars in Eclipse?

The rest assured jar files can be downloaded from the following link.

https://github.com/rest-assured/rest-assured/wiki/Downloads.

When we navigate to this page, we can see the section “Current direct downloads”. Go to this section and click on
the link to the dist package.

Note: At the time of this writing Version 4.4.0 is available for download.

Once the link is clicked, the browser will download the rest-assured-4.4.0-dist.zip file on the system (mostly in the
"downloads" folder for Windows OS). Navigate to the folder where the zip file was downloaded and simply unzip the
files.

Now go to the folder where the files were just unzipped and open it. The contents should be the following in this
folder.

• docs: A folder containing javadocs.

• rest-assured-3.0.3.jar: jar file that contains rest-sssured classes.

• rest-assured-3.0.3-deps.zip: Another zip file containing all the dependency jars.

Note: We have to also unzip the rest-assured-4.4.0-deps.zip dependency jars. In the end, your folder would look like
this.

Page | 72
Now that we have rest assured jars package ready, we can go ahead and create a project in Eclipse that will use rest
assured.

Creating a project in Eclipse for rest assured

To add and use unzipped rest assured jars in an actual project, we have to first create a new project in Eclipse. So we
create a project, let's say, RestAssuredTest as shown below.

Page | 73
Once clicked on the Java Project link, a new project window opens up. Enter the name of the project
as RestAussuredTest and click on the Finish button. Once Finish is clicked, we get the following screen. Click Open
Perspective. (Alternatively, if we have already checked the option "remember my decision", then this step will not be
seen)

Page | 74
Now the project with the name RestAssuredTest should display in the package explorer.

Page | 75
Once the project is created in Eclipse, now it is required to add the unzipped jars in the classpath of the Eclipse
project.

How to setup rest-assured jars in the class path?

Select the Java project folder we just created and right-click on the project folder in the package explorer pane and
choose Properties. This will open up the project properties pop-up window as shown below.

Select Java build path option in the left pane of the properties window. In the Java build path pane, on the left-hand
side, you will see the Libraries pane.

Page | 76
Here we are going to reference the rest assured jar files that we downloaded earlier. To reference the jars, click on
the "Add external jars" button and navigate to the folder where we unzipped all our rest-assured jars. Refer to the
image shown below.

Now include the following Jars

• rest-assured-3.3.0.jar

• All the jars in the folder rest-assured-3.3.0-deps

With this, we have successfully set up a Java project in Eclipse with a rest-assured library. If we now check the
project explorer, we will get the following view.
Page | 77
Now we are ready to use Rest Assured features in Eclipse.

REST API Testing using Rest Assured


In our last article, witnessed the steps to configure Eclipse in our last article titled Configuring Eclipse with Rest-
assured. Continuing on the same path, in this article, we will discuss writing our first API test using Rest Assured.
Along with that, we will also discuss the basics of REST API testing briefly in this chapter. This chapter assumes that
the reader has good knowledge of the TestNG Framework. Thus we will cover the following topics in this article.

• What is REST API Testing?

• HTTP Methods and status codes for REST API Automation Testing

• REST API test using Rest Assured

o How to Write REST API Test using Rest Assured?

o Understanding Rest Assured code for REST API Testing

What is REST API testing?

Rest stands for Representational State Transfer and is an architectural style for communication with web services.
An API or Application Programming Interface is a set of programming instructions used to access a web-based
software application. The APIs built using REST is called REST APIs which we have discussed in an earlier article. Let
us now begin to understand REST API testing.
Page | 78
So what is REST API testing?

REST API testing is a technique to test RESTful APIs and validate their correctness. We send the request (preferably
using automation) and record the response for further assertions. This way we can check if the REST API is working
fine or not. REST API testing is mainly done using four REST methods, viz, GET, POST, PUT, DELETE.

There are two approaches to test the REST API:

1. Manual testing: Similar to any other manual testing of applications

2. Automation testing: Using scripts or programs that can access REST APIs.

However, in this tutorial, we will only concentrate on automated REST API testing.

HTTP Methods and status codes for REST API Automation Testing

We know that REST API uses five HTTP methods to request a command:

Method Description

GET Retrieves the information at a particular URL.

PUT Updates the previous resource if it exists or creates new information at a particular URL.

POST Used to send information to the server like uploading data and also to develop a new entity.

DELETE Deletes all current representations at a specific URL.

PATCH This is used for partial updates of resources.

Once the request is sent using the above methods, the client receives the numeric codes known as "Status codes" or
sometimes referred to as "Response codes". Then we can interpret these status codes to know what kind of
response the server has sent for a particular request. Status codes are mainly classified into five categories as shown
in the table below.

No Status Code Description

1 1xx (100 – 199) The response is informational.

2 2xx (200 – 299) Assures successful response.

3 3xx (300 – 399) You are required to take further action to fulfil the request.

4 4xx (400 – 499) There’s a bad syntax and the request cannot be completed.

5 5xx (500 – 599) The server entirely fails to complete the request.

The above codes help us to interpret the outcome of the HTTP requests. From the above table, we can deduce that if
the response status code is 2xx, it means the application is functioning as it should be. The status code 1xx, 2xx, 3xx
are not considered errors but are informative messages and these codes will not affect the user experience.

However, if we get status codes like 4xx and 5xx, these are error messages. This means users will encounter error
messages when they are navigating through the APIs. Errors at the client or browser level mostly result in 4xx status
code error messages. Whereas server-level errors result in 5xx status code error messages. So when performing
REST API testing we should evaluate each response by inspecting the error codes.

Consider the following REST API example URL, https://demoqa.com/swagger/#/BookStore. This is a bookstore
inventory and it provides us with various REST API methods to access information from the bookstore. Now let us
access this URL in the browser and we are presented with the following screen.

Page | 79
Click on the GET method (the first one) in the above store to access the pet inventory. When we click and execute
the GET method, we get the following response.

Note the status code on the above screen (left panel). It is 200 which means the request was successfully executed
and we got a successful response. This way we receive a status code from the server when we send a request and
then we can interpret this status code and check if the request was executed in a normal manner or some error
occurred. We will further explore the response obtained from the server in our upcoming articles.

REST API test using Rest Assured

REST Assured is a Java library for testing RESTful APIs. It is widely used to test JSON and XML-based web applications.
In addition, it fully supports all REST methods like the GET, PUT, POST, PATCH, and DELETE. Next, we will see a
detailed walkthrough of testing one REST API using the Rest Assured library.

How to write REST API test using Rest Assured?

To write a sample REST API test we will make use of the following REST API link.

Request
https://demoqa.com/BookStore/v1/Books
URL

HTTP
GET
Method

This URL will return the inventory details of a Book store. There are no input parameters for the
Comments
request.

Page | 80
{"books": [{"isbn": "string","title": "string","subTitle": "string","author":"string","publish_date": "2022-
Response
01-25T13:44:50.276Z","publisher": "string","pages": 0,"description": "string","website": "string"}]}

In fact, if we directly open the above URL in the browser, we get this output as shown below:

To get the same output programmatically using the Rest Assured library, we have to follow below steps:

1. Use the RestAssured class to generate a RequestSpecification for the


URL: https://demoqa.com/BookStore/v1/Books

2. Specify the HTTP Method type (GET method).

3. Send the Request to the server.

4. Get the Response back from the server.

5. Print the returned Response’s body.

Below given is the complete code for the above steps:

import io.restassured.RestAssured;

import io.restassured.http.Method;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class RestAssuredAPITest {

@Test

public void GetBooksDetails() {

// Specify the base URL to the RESTful web service

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

// Get the RequestSpecification of the request to be sent to the server.

RequestSpecification httpRequest = RestAssured.given();

// specify the method type (GET) and the parameters if any.

//In this case the request does not take any parameters

Response response = httpRequest.request(Method.GET, "");

// Print the status and message body of the response received from the server

System.out.println("Status received => " + response.getStatusLine());


Page | 81
System.out.println("Response=>" + response.prettyPrint());

The above code generates the same response as we got in the browser earlier. The following screenshot shows the
response.

In this way, we can make any Test API call and get the response from the webserver hosting RestFul services.

Understanding Rest Assured code for REST API Testing

Let us now walk through the code we implemented above.

Code line 1

// Specify the base URL to the RESTful web service

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

The above line uses RestAssured class to set up a base URI. In this case, the base URI
is “https://demoqa.com/BookStore/v1/Books”. The base URI indicates the root address of the resource we are
going to request from the server (hence the name base URI). Then we will add parameters, if any, when we actually
make the request in subsequent code.

The class io.restassured.RestAssured , is the basis of any kind of HTTP request we make for tests. Some of the key
features of this class are:

• It generates HTTP Requests with a base URI.

• Provides support to create Requests for different HTTP method types (GET, POST, PUT, PATCH, DELETE,
UPDATE, HEAD, and OPTIONS).

• It communicates with the server using HTTP and sends the Request created in the tests to the server.

• Receives the response from the server.

• Provides support for validating the Response received from the server.

Internally io.restassured.RestAssured class uses an HTTP builder library, which is a Groovy language-based HTTP
client.

Code line 2
Page | 82
// Get the RequestSpecification of the request to be sent to the server.

RequestSpecification httpRequest = RestAssured.given();

The next line gets the RequestSpecification of the request to be sent to the server. Rest Assured library provides an
interface called RequestSpecification for this purpose. The variable httpRequest stores the request so that we can
modify it if required like adding authentication details, adding headers, etc. For this particular test, we are not
modifying the variable.

Code line 3

// specify the method type (GET) and the parameters if any.

//In this case the request does not take any parameters

Response response = httpRequest.request(Method.GET, "");

Now we call the server to get the resource using the RequestSpecification object. The above code line uses the
request method to send the request for the resource to the server.

The request method takes two arguments, the first is the HTTP method and the second is a string. The string
parameter is used to specify the parameters that are to be sent with the base URI. In this case, to get pet store
details we do not send any parameters hence the blank string. The return type of the request method is
the Response object which means the request method gets the response back from the server.

The Response interface (io.restassured.response.Response) represents a response returned from a server. It


contains all the data sent by the server. As we will see in the subsequent articles, we can call different methods on
this response object to extract the response like response status, headers, etc.

Code line 4 and 5

// Print the message body of the response received from the server

System.out.println("Status received => " + response.getStatusLine());

System.out.println("Response=>" + response.prettyPrint());

In the above code lines, we just read the response as a string and print it to the console. We use the getBody method
of response interface that returns the actual body of the response. This is then printed to the console.

We can also write the above test code using short-hand methods provided by Rest Assured. Following is the code
snippet that is shortened a bit.

@Test

public void GetWeatherDetailsCondensed()

// Specify the base URL to the RESTful web service

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

// Get the RequestSpecification of the request that is to be sent

// to the server.

RequestSpecification httpRequest = RestAssured.given();

Page | 83
// Call RequestSpecification.get() method to get the response.

// Make sure you specify the resource name.

Response response = httpRequest.get("");

// Response.asString method will directly return the content of the body

// as String.

System.out.println("Response Body is => " + response.asString());

So here we use the "get" method on the RequestSpecification object that returns the Response object.

We will refer to the same example in our next articles when we go into details of
the io.restassured.response.Response interface.

Note: The postman article on the same topic (API test and GET request) can be found at New Request in
Postman and Get Request in Postman.

Validate Response Status using Rest Assured


Every HTTP Response received as a result of an HTTP request sent by the client to the server has a status code. This
status code value tells us if HTTP Response was successful or not. This article is a continuation of our previous article
in which we performed a sample REST API test call. In this article, we will discuss how to validate the HTTP response
status using REST Assured. The content of the post is reflected by the following index:

• Validate HTTP Response Status using Rest Assured

• How to validate HTTP response status code

• Validating the HTTP error status code?

• How to validate HTTP Response Status Line?

Validate HTTP Response Status using Rest Assured

An HTTP response object typically represents the HTTP packet (response packet) sent back by Web Service Server in
response to a client request. An HTTP Response contains:

1. A status.

2. Collection of Headers.

3. A Body.

We have a detailed article on HTTP Response here.

So when we say we need to validate HTTP response status, we are looking forward to having a mechanism to read
and validate the entire response object including the status, headers, and the body. Hence, we will validate each of
the HTTP response components separately. So in this article, the validation of an HTTP response status will be dealt
with in three parts as follows:

• Validating HTTP Response Status Code.

• How to validate the Error Status Code

• Validating Response Status Line.

Page | 84
As we already know the same REST API returns a response message in XML or JSON format. This format depends on
the Media-Type attribute in the HTTP request.

But then how will the client know what type of response it will get from the API? Well, this is managed by the
response headers. Response Header contains a Content-Type attribute that informs about the type of response body
format.

Consider the Swagger UI example we discussed in earlier articles. Suppose we send a GET request to the Book Store
through our browser as follows:

curl -X GET "https://demoqa.com/BookStore/v1/Books" -H "accept: application/json"

When the above command executes we obtain the response shown in below screen:

As seen from the above screenshot, the response has a status, headers, and a body. If we check the "Response
headers" section, in the above screen, it has a content-type attribute that has the value along with other attributes.
On validating this header, the client knows what type of response (body) we can expect.

Let us now proceed with validating the status part of the response.

How to validate HTTP response status code

When the client requests a piece of particular information from the server, the server sends a response with a status
code back to the client. The status code that the server returns tells us whether the request was successful or not. If
the request was successful, the server sends the status code in the range of 200-299. If the request was not
successful, then the status code other than the range is returned. We can get the list of HTTP status codes along with
their description on the W3 page.

Rest Assured library provides a package named "io.restassured.response" which has a Response interface. The
Response interface provides methods that can help to get parts of the received response. The following screenshot
shows some of the important methods of the response interface.

Page | 85
The method getStatusCode() is used to get the status code of the response. This method returns an integer and then
we can verify its value. TestNG Assert is used to verify the Status Code. Now consider the code given below:

import static org.junit.Assert.*;

import org.testng.Assert; //used to validate response status

import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class RestAssuredTestResponse {

@Test

public void GetBookDetails()

// Specify the base URL to the RESTful web service

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

// Get the RequestSpecification of the request to be sent to the server

RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("");

// Get the status code of the request.

//If request is successful, status code will be 200

Page | 86
int statusCode = response.getStatusCode();

// Assert that correct status code is returned.

Assert.assertEquals(statusCode /*actual value*/, 200 /*expected value*/,

"Correct status code returned");

The below line of code extracts the status code from the message:

int statusCode = response.getStatusCode();

The return value "statusCode" is compared with the expected value i.e. 200. If both values are equal, then an
appropriate message is returned.

// Assert that correct status code is returned.

Assert.assertEquals(statusCode /*actual value*/, 200 /*expected value*/, "Correct status code returned");

If you run the above test, you will see that the test passes since the web service returns the status code as 200 as
shown in the below image.

In this manner, we can verify the status code of the response using the "getStatusCode()" method of the response
interface. Please note that since we already knew that the success code here is 200, we wrote the appropriate code.
Your server may respond as success with a code anywhere between 200 and 299. It is best to check that out
beforehand. Let us now move on to discuss how to validate the status code that returns values other than 200 i.e.
error status code.

How to validate the HTTP error status code?

So far the request-response situations are all good and we have only received 200 status codes indicating successful
requests. But this may not be always true in the real world. There can be reasons like the server is down or REST API
not functioning properly or the requests themselves may be problematic. In conclusion, we may face the following
scenarios:

1. The server hosting REST API is down.

2. Incorrect client request.

3. The resource requested by the client does not exist.

4. An error occurs on the server side during the processing of the request.

So when any of the above scenarios occur, the REST API will return an appropriate status code other than 200. The
client in turn has to validate this status code and process it accordingly.
Page | 87
For the ToolsQA Book Store service, let’s create another test with an erroneous scenario. Here we will validate the
HTTP status code returned by Book store Web Service when an invalid parameter is entered.

So here we provide the parameter to get user details. Here we provide nonexistent userId as the parameter. The
code looks as below:

import static org.junit.Assert.*;

import org.testng.Assert; //used to validate response status

import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class RestAssuredTestResponse {

@Test

public void GetPetDetails()

// Specify the base URL to the RESTful web service

RestAssured.baseURI = "https://demoqa.com/Account/v1/User/";

// Get the RequestSpecification of the request to be sent to the server

RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("test");

// Get the status code of the request.

//If request is successful, status code will be 200

int statusCode = response.getStatusCode();

// Assert that correct status code is returned.

Assert.assertEquals(statusCode /*actual value*/, 200 /*expected value*/,

"Correct status code returned");

When we run this test it returns the error code of 401. We can see the result of the test execution below.

Page | 88
Note: We can make a quick change to the code above to make sure the test passes. This change is shown below:

Assert.assertEquals(statusCode /*actual value*/, 401 /*expected value*/, "Correct status code returned");

So here we expect the value returned to be 401 instead of 200, hence the test is passed. Next, we will validate
the "Status line".

How to validate the response status line?

A "Status-Line" is the first line returned in the HTTP response. The status line consists of three substrings:

• HTTP protocol version.

• Status Code.

• Status Code’s string value.

For example, when the request is successful the status line will have the value "HTTP/1.1 200 OK". Here, the first
part is the HTTP protocol (HTTP/1.1). Next is the HTTP status code (200). The third is the status message (OK).

We can read the entire status line using the method getStatusLine () of the response interface. The following code
shows the demonstration.

@Test

public void GetBookDetails()

// Specify the base URL to the RESTful web service

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

// Get the RequestSpecification of the request to be sent to the server

RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("");

// Get the status line from the Response in a variable called statusLine

String statusLine = response.getStatusLine();

Assert.assertEquals(statusLine /*actual value*/, "HTTP/1.1 200 OK"

/*expected value*/, "Correct status code returned");

Here we perform a similar test as we have done for the status code. We read the status line using the
getStatusLine () method into a string value. Then we compare this returned value with "HTTP/1.1 200 OK" to check if
the status is successful.

Note: The postman article on the same topic (Response in Postman) can be found at Response in Postman.

Page | 89
Validate Response Header using Rest Assured
REST assured has been of great use to us for testing APIs and validating a lot of things. For instance, in the last
tutorials, we performed a sample Test call using Rest Assured and also validated response status. But that is just one
part of the overall response testing when it comes to automation. There is a lot more that we need to validate in
order to be an efficient tester and test the quality of our APIs. In this article, let us validate the Response Header
using Rest Assured with the following topics in focus:

• What is an HTTP Response Header in REST API?

• REST Assured methods for validating HTTP Response Headers.

• How to access and read HTTP Response headers using REST Assured?

• How to validate Response Header using Rest Assured.

What is an HTTP Response Header in REST API?

The response received from the server consists of zero or more headers along with response status and response
body. Each header is a key-value pair. The header part of the response is used by the server to send extra
information which is also referred to as "Metadata" of the response.

For example, headers contain a "Content-Type" attribute that tells us how to interpret the data of the response
body. So if the response body contains JSON data, then the corresponding content-type attribute in the header will
be "application/json". Similarly, if the data in the body is XML the Content-Type header will be "application/xml".

For example, for the following request URL: https://demoqa.com/BookStore/v1/Books

when we give the following GET request:

curl -X GET "https://demoqa.com/BookStore/v1/Books" -H "accept: application/json"

we get the following response.

Note the response header that is obtained (red rectangle). Since the body is JSON, the Content-Type is set to
"application/JSON".

Rest Assured methods for validating HTTP Response Headers

The Response interface of the Rest Assured library provides methods to access all headers or individual headers. Just
typing "Response.head" in Eclipse (or any such editor) will show all the methods supported to access headers.

As shown in the above screenshot, the Response interface of REST Assured provides methods related to headers.

• headers() : returns Headers

• getHeader(): returns a Header

• getHeaders(): returns Headers

When all the headers in a Response are returned, we can print each header by simply iterating over each of them.

Page | 90
Note: The collection of headers is represented by a class called io.restassured. HTTP.Headers. This class implements
the Iterable interface. Hence, we can use the "for each (for( : ))" loop to read all the headers.

How to access and read HTTP Response headers using REST Assured?

Now let us see how we can read a Header using Rest-Assured. Let’s write a test to record the following Header Types
from the Response:

• Content-Type.

• Server.

• Content-Encoding.

Shown below is the code for this test:

@Test

public void IteratingHeaders()

{ RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("");

// Get all the headers and then iterate over allHeaders to print each header

Headers allHeaders = response.headers();

// Iterate over all the Headers

for(Header header : allHeaders) {

System.out.println("Key: " + header.getName() + " Value: " + header.getValue());

In the above code, we access all headers and then extract individual headers by looping through the Headers
collection. Shown below is the console output of the above test.

The above output shows all the header key-value pairs that we displayed using for loop in the code.

Let us demonstrate the .header(String arg0) method to get a particular header. Here we pass the exact header
name as an argument.

@Test

public void GetBookHeaders() {

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

RequestSpecification httpRequest = RestAssured.given();


Page | 91
Response response = httpRequest.get("");

// Access header with a given name.

String contentType = response.header("Content-Type");

System.out.println("Content-Type value: " + contentType);

// Access header with a given name.

String serverType = response.header("Server");

System.out.println("Server value: " + serverType);

// Access header with a given name. Header = Content-Encoding

String acceptLanguage = response.header("Content-Encoding");

System.out.println("Content-Encoding: " + acceptLanguage);

In the above code, we are accessing Content-Type, Server, and Content-Encoding headers by specifying respective
headers names as an argument to the header() method. Shown below is the console output of the above code.

Note: Response.GetHeader(String headerName) method behaves exactly the same way as the
Response.Header(String headerName) method. So the above code can be written by replacing the ".Header()"
method with the ".GetHeader()" method.

How to validate HTTP Response Header using Rest Assured?

Now that we have had a discussion about methods that access header, let us write a test to validate the values of
the header by putting it as Assert. The below code shows the test that is similar to the code in previous sections but
only uses Assert to validate the results.

@Test

public void ValidateBookHeaders()

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("");

// Access header with a given name. Header = Content-Type

String contentType = response.header("Content-Type");

Assert.assertEquals(contentType /* actual value */, "application/json; charset=utf-8" /* expected value */);


Page | 92
// Access header with a given name. Header = Server

String serverType = response.header("Server");

Assert.assertEquals(serverType /* actual value */, "nginx/1.17.10 (Ubuntu)" /* expected value */);

In the above code, we verify the actual value of each header viz., Content-Type, Server, and Content-Encoding with
the expected value. Shown below is the screenshot of the test result.

This output indicates that the actual value and expected value of each header matches.

Now suppose we provide the expected value of Content-Type to "application/XML" in the above code as below.

Assert.assertEquals(contentType /* actual value /, "application/xml" / expected value */);

If we run the same test above after the change, we will get the following output.

As we can see, the difference in actual value "application/JSON" and the expected value "application/XML" raises
an assertion error.

In this way by using the header-specific methods of Response interface, we can validate the Response Header in Rest
API.

Read JSON Response Body using Rest Assured


In the last two tutorials we have learnt about Response Status Code, Status line and Headers. We will continue with
the same example in those tutorials and verify the body if the Response. If you have not gone through the first two
tutorials then I would suggest you go through these links

• First Test with Rest-Assured

• Validate Response Status code and Status Line using Rest-Assured

• Validate Response Header using Rest-Assured

In this tutorial, we will learn about How to Read JSON Response Body using Rest Assured? and How to Validate
Content of a Response Body?

Read JSON Response Body using Rest Assured

Let us continue with the example of Weather web service that we used in the previous tutorials. When we request
for the Weather details of a particular city, Server responds by sending the Weather details of the city as the
Response Body. Response interface contains two methods to get the Response Body

• Response.body() : returns ResponseBody

• Response.getBody() : returns ResponseBody

Page | 93
Using these methods we can get an Object of type io.restassured.response.ResponseBody. This class represents the
Body of a received Response. Using this class you can get and validate complete or parts of the Response Body. In
the below code we will simply read the complete Response Body by using Response.getBody() and will print it out
on the console window.

@Test

public void WeatherMessageBody()

RestAssured.baseURI = "https://restapi.demoqa.com/utilities/weather/city";

RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("/Hyderabad");

// Retrieve the body of the Response

ResponseBody body = response.getBody();

// By using the ResponseBody.asString() method, we can convert the body

// into the string representation.

System.out.println("Response Body is: " + body.asString());

ResponseBody interface also has a method called .asString(), as used in the above code, which converts
a ResponseBody into its String representation. If you run this test the output will look something like this:

Page | 94
Note: Response.body() method does exactly the same thing. So you can even use .body() method in the above code.

How to Validate Response Body contains some String?

ResponseBody can return the response body in a String format. We can use simple String methods to verify certain
basic level of values in the Response. For e.g. we can use the String.contains() method to see if the Response
contains a "Hyderabad" in it. The below code shows how to check for sub string presence.

@Test

public void WeatherMessageBody()

RestAssured.baseURI = "https://restapi.demoqa.com/utilities/weather/city";

RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("/Hyderabad");

// Retrieve the body of the Response

ResponseBody body = response.getBody();

// To check for sub string presence get the Response body as a String.

// Do a String.contains

String bodyAsString = body.asString();

Assert.assertEquals(bodyAsString.contains("Hyderabad") /*Expected value*/, true /*Actual Value*/,


"Response body contains Hyderabad");

Check String presence by ignoring alphabet casing

We can also ignore the casing using the String internal methods. To do this we will convert the Response in lower
case and then compare it with our lower case string value. Below code demonstrates that.

@Test

public void WeatherMessageBody()

RestAssured.baseURI = "https://restapi.demoqa.com/utilities/weather/city";

RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("/Hyderabad");

// Retrieve the body of the Response

ResponseBody body = response.getBody();

// To check for sub string presence get the Response body as a String.

Page | 95
// Do a String.contains

String bodyAsString = body.asString();

// convert the body into lower case and then do a comparison to ignore casing.

Assert.assertEquals(bodyAsString.toLowerCase().contains("hyderabad") /*Expected value*/, true /*Actual


Value*/, "Response body contains Hyderabad");

The above two approaches suffer from a classical problem, what if the string "Hyderabad" is present in a wrong
node or may be multiple instances of the same string are present. This is not a fool proof way of testing a particular
node in the Response. There are better ways, Response interface gives you a mechanism to extract nodes based on a
given JsonPath. There is a method called Response.JsonPath(), which returns
a io.restassured.path.json.JsonPath Object. This object can be used to further query specific parts of the Response
Json.

If you are not aware of JsonPath, please go through these tutorials

• What is JsonPath

• JsonPath expressions

How to Extract a Node text from Response using JsonPath?

Let us continue with the above example and retrieve the City from the Response. To do so, we will simply get
the JsonPath object from the Response interface and then query for the particular node. Just to be very clear, let us
look at the Weather API response again.

"City": "Hyderabad",

"Temperature": "25.51 Degree celsius",

"Humidity": "94 Percent",

"Weather Description": "mist",

"Wind Speed": "1 Km per hour",

"Wind Direction degree": " Degree"

In this response, if we want to go to the City node, all we have to do is have the following JsonPath: $.City. Try it out
on the JsonPath Evaluator to verify the output.

Now let us look at the code, pay specific attention to the comments in the code.

Note: In Java JsonPath you do not need to have $ as the root node. You can completely skip that.

@Test

public void VerifyCityInJsonResponse()

RestAssured.baseURI = "https://restapi.demoqa.com/utilities/weather/city";
Page | 96
RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("/Hyderabad");

// First get the JsonPath object instance from the Response interface

JsonPath jsonPathEvaluator = response.jsonPath();

// Then simply query the JsonPath object to get a String value of the node

// specified by JsonPath: City (Note: You should not put $. in the Java code)

String city = jsonPathEvaluator.get("City");

// Let us print the city variable to see what we got

System.out.println("City received from Response " + city);

// Validate the response

Assert.assertEquals(city, "Hyderabad", "Correct city name received in the Response");

The output of the code passes the assertion and it also prints the City name retrieved from the Response. As shown
in the image below

On the similar lines, you can extract any part of the Json response using the JsonPath implementation of Rest-
Assured. This is very convenient, compact and easy way to write tests.

Sample Code to read all the nodes from Weather API Response

Now that we know how to read a node using JsonPath, here is a small piece of code that reads all the nodes and
prints them to the Console.

@Test

public void DisplayAllNodesInWeatherAPI()

RestAssured.baseURI = "https://restapi.demoqa.com/utilities/weather/city";

RequestSpecification httpRequest = RestAssured.given();


Page | 97
Response response = httpRequest.get("/Hyderabad");

// First get the JsonPath object instance from the Response interface

JsonPath jsonPathEvaluator = response.jsonPath();

// Let us print the city variable to see what we got

System.out.println("City received from Response " + jsonPathEvaluator.get("City"));

// Print the temperature node

System.out.println("Temperature received from Response " + jsonPathEvaluator.get("Temperature"));

// Print the humidity node

System.out.println("Humidity received from Response " + jsonPathEvaluator.get("Humidity"));

// Print weather description

System.out.println("Weather description received from Response " + jsonPathEvaluator.get("Weather"));

// Print Wind Speed

System.out.println("City received from Response " + jsonPathEvaluator.get("WindSpeed"));

// Print Wind Direction Degree

System.out.println("City received from Response " + jsonPathEvaluator.get("WindDirectionDegree"));

Working with Query Parameters in Rest Assured | REST API


So far in this series, we have covered reading the response body. But as you proceed ahead, a simple GET or a POST
request won't suffice to the complexity your test scenario might have. You may need to test the API for different
query parameters. In this article, we will cover how query parameters are passed in the HTTP request using rest
assured with the following main sections-

• What is the composition of the URL?

• What are Query Parameters?

• How to send a request using Query Parameters in Rest Assured?

What is the composition of the URL?

Similar to the examples used in the previous articles we will be using the Bookstore API in this article as well.
Consider the below sample URL to fetch details corresponding to a book-

Page | 98
https://demoqa.com/BookStore/v1/Book?ISBN=9781449325862 Though the above URL looks very basic, it still let
us understand its different components.

• https:// - It is a protocol that ensures secure connection between the web server and the web browser.

• https://demoqa.com/swagger/#/BookStore - It is the domain name that hosts the website. It generally ends
with .com, .in, .net, etc.

• BookStore/v1/Book - This is the path or the URI that identifies the resource applied by the request.

• ?ISBN=9781449325862 - This is a string query parameter. The question mark denotes the start of a query
string parameter. There can be one or more query parameters in the URL.

Let us now understand more about query parameters in the next section.

What are Query String Parameters?

You might not always want to fetch all the results corresponding to a request. There may be scenarios where you
need to fetch only a few or a single record. In such cases, query string parameters play an important role. These are
appended at the end of the URL after using a '?'. Try entering the example URL in the browser address bar and
observe the results available under Network -> Payload-

The query parameter, i.e., ISBN=9781449325862, is displayed under the Query String Parameters field. In a similar
way, if there are multiple query parameters passed in the URL, you will see all of them in this field. As an exercise,
you may search some keywords on Google search and see the query parameters that get appended to the URL.
Observe the search keyword is displayed after 'q=your search keyword'. Additionally, you will observe other query
parameters which are separated from each other through an '&' sign.

These signs are termed URL parameters and are beyond the scope of our discussion here.

Now that we have understood what query parameters are and how they are used in requests, we can proceed to see
how we can send requests with Query Parameters in Rest Assured.

How to send a request using Query Parameters in Rest Assured?

In this section, we will see how we can automate our test case by passing query parameters in Rest assured. We will
simply use the URL containing the query parameter as discussed in sections above to show how we can send a
request using query parameters in rest assured. Let us see how the code would look like and then we will
walkthrough it step by step.

package bookstore;

import org.junit.Test;

import io.restassured.RestAssured;

import io.restassured.path.json.JsonPath;

import io.restassured.response.Response;

import io.restassured.response.ResponseBody;

import io.restassured.specification.RequestSpecification;

Page | 99
public class QueryParam {

@Test

public void queryParameter() {

//Defining the base URI

RestAssured.baseURI= "https://bookstore.toolsqa.com/BookStore/v1";

RequestSpecification httpRequest = RestAssured.given();

//Passing the resource details

Response res = httpRequest.queryParam("ISBN","9781449325862").get("/Book");

//Retrieving the response body using getBody() method

ResponseBody body = res.body();

//Converting the response body to string object

String rbdy = body.asString();

//Creating object of JsonPath and passing the string response body as parameter

JsonPath jpath = new JsonPath(rbdy);

//Storing publisher name in a string variable

String title = jpath.getString("title");

System.out.println("The book title is - "+title);

RestAssured.baseURI= "https://bookstore.toolsqa.com/BookStore/v1";

RequestSpecification httpRequest = RestAssured.given();

We first define the base URI to create a request to the service endpoint.

Response res = httpRequest.queryParam("ISBN","9781449325862").get("/Book");

Next we send the resource details like the book ISBN as a query parameter to search in books using the GET request.

Note: If you need to send multiple query parameters you simply need to append queryParam() method with the
parameter name and value to the RequestSpecification object, i.e. httpRequest in the above case.

ResponseBody body = res.body();

String rbdy = body.asString();

JsonPath jpath = new JsonPath(rbdy);

String title = jpath.getString("title");

Page | 100
System.out.println("The book title is - "+title);

Finally, we are storing the response body as a String object and parsing its different values using the JSONPath object.
We then fetch the title from the response body.

Note: You may read more about JSONPath in our elaborate article on the same.

And that's it! See how easily we could send the query parameters to our request by simply using
a queryParam() method. The above code execution displays the title of the book with respect to the ISBN.

You can now go ahead with automating your test scripts with request having query parameter(s) and enhance your
rest assured code.

Understanding HTTP POST Request Method using Rest Assured


In our discussions of HTTP REST Methods, we went through the GET request in our earlier tutorials. We have also
discussed validations like validating headers and the status of the response obtained from the server. In this article,
we'll discuss the next method in REST API i.e. the POST request using Rest Assured library.

What is an HTTP Post Request method?

We use the verb "Post" everywhere when we are dealing with the web. For example, when we are submitting any
registration form on a particular webpage like Gmail. We provide the required data and click submit. So through this
action of submitting data, we are actually POSTING or sending the data to the server. The verb "POST" in HTTP, also
called as POST request method in HTTP sends data to the server. In our example, we are sending our names, email
and decided password as data.

Now let's go to Swagger UI of API https://demoqa.com/BookStore/v1/Books Next, let's create a new user using
POST request as shown in the following screenshot.

In the above example, we have provided all the details for the new user including id and ISBN. When we "execute"
requests we initiate a POST request and send all the information to the server. On the server side, the new user will
Page | 101
be created with all the provided information and a response will be sent back to the client. Look at the following
screenshot.

Have a look at the "curl" command that has a POST request with all the data. The operation is successful and hence
we get the response code as 201.

The content-type parameter is "application/JSON" in the above example. The data sent to the server by POST
request can also be XML(content-type: application/XML). This data is in the body of the HTTP request. As we learned
from the above example, the POST method usually creates a new record in the application database. Although, it is
not always true. Sometimes in creating web applications we use POST request redirections to ensure that no one hits
that URL directly without proper navigation channels. For example, you must have noticed that refreshing or
pressing "back" on payment pages does not work directly. It is secure as the data being sent is not visible in the URL
string. The data can also be encrypted using HTTPS (HTTP Secure) to enhance security.

As far as real-world applications are concerned, the POST request can have a very big size and also a complex body
structure. Since it provides an extra layer of security, we often use it for passing sensitive business-related data. It is
also noteworthy here that the POST request does not always require all the data to be filled by the user. It
completely depends on the server implementation and therefore you should always go through the documentation
before.

Let us now use Rest Assured to simulate an HTTP POST request.

How to use POST Request Method using Rest Assured?

In Rest Assured, we make use of the post() method to make an HTTP POST request.

For making an HTTP Post request using Rest Assured, let's add a simple JSON library in our classpath so that we can
create JSON objects in the code. We can use the following URL to download simple JSON from the
Maven: https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple. Once the jar is downloaded
we can add it to the classpath.

Following are the steps we'll follow to make a POST Request using Rest Assured.

1. Create a Request pointing to the service Endpoint.

2. Create a JSON Request which contains all the fields.

3. Add JSON body in the request and send the request.

4. Validate the Request.

5. Changing the HTTP Method on a POST Request.

Let us now perform each step one by one.


Page | 102
Create a Request pointing to the Service Endpoint

We can start coding once the JSON jar downloads.

Consider following code lines.

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

RequestSpecification request = RestAssured.given();

In the above code, we initialize a base URI with a link to the bookstore and the 'createUser' API. Next, we create a
'request' using RequestSpecification.

Note: Above code is self-explanatory. In case of any problems, please refer to previous tutorials.

Create a JSON request which contains all the fields

Next, we will create a JSON request object that will contain the data we need to create a new user. Given below is
the code for the same:

// JSONObject is a class that represents a Simple JSON.

// We can add Key - Value pairs using the put method

JSONObject requestParams = new JSONObject();

requestParams.put("userId", "TQ123");

requestParams.put("isbn", "9781449325862");

In the above code, we have created a JSONObject variable (JSONObject belongs to org.json.simple package). Here
we provide a JSON String containing the data to post to the server. Here we have the requestParams object above
for our test web service with multiple nodes in the JSON. Each node is added to the JSON string using
the JSONObject.put(String, String) method. Once all the nodes are added in this manner, we get the String
representation of JSONObject by calling JSONObject.toJSONString() method.

Add JSON body in the request and send the Request

Now that we have created the JSON string with the required data, the next step will be to add this JSON to the
request body and send or post the request. Look at the following code:

// Add a header stating the Request body is a JSON

request.header("Content-Type", "application/json"); // Add the Json to the body of the request

request.body(requestParams.toJSONString()); // Post the request and check the response

So in this step, we simply add the JSON String to the body of the HTTP Request and set the Content-Type header
field value to application/JSON. Next, we use the method RequestSpecification.body(JsonString) to put the JSON
body into the request. Using this method we can update the content of the HTTP Request Body.

Next using the post () method on the request object we send this data to the server using the
'BookStoreV1BooksPost' API.

Note: Calling the RequestSpecification.body method multiple times updates the body each time to the latest JSON
String.

Validate the Response

After posting the request we have to validate the response we received from the server as a result of a POST
request. Given below is the code for validating the response:

Response response = request.post("/BookStoreV1BooksPost");


Page | 103
System.out.println("The status received: " + response.statusLine());

Here we read the status obtained using the statusLine() method and print it to the console.

Changing the HTTP Method on a POST Request using Rest Assured

So what happens when we change the HTTP Request method on a POST request? For example what happens when
instead of the expected POST we send the GET? Let's discuss this scenario.

Following is the code wherein we have sent a GET request to an Endpoint when it actually expects POST.

public void UserRegistrationSuccessful()

RestAssured.baseURI ="https://demoqa.com/Account/v1";

RequestSpecification request = RestAssured.given();

JSONObject requestParams = new JSONObject();

requestParams.put("userName", "test_rest");

requestParams.put("password", "Testrest@123");

request.body(requestParams.toJSONString());

Response response = request.put("/User");

ResponseBody body = response.getBody();

System.out.println(response.getStatusLine());

System.out.println(body.asString());

When we execute the above code, we get the following response.

We can clearly see the output says the incorrect usage of the HTTP Request Method. Similarly, we have other
negative scenarios listed below which we will leave to users to try themselves.

• Sending incomplete POST Data.

• Try Sending JSON data with incorrect syntax.

• Sending incorrect HTTP request method in the Request.

You can try the above scenarios on the same URL used above to demonstrate the POST request.

Page | 104
Serialization and Deserialization in Java
Serialization and Deserialization in Java is an important programming concept. It is applicable to all major
programming languages. In this chapter, we will try to understand this concept in the context of Java language. At
the end of this chapter, we will be able to

• Conceptually know meaning of Serialization and Deserialization

• Understand the Java code to Serialization and Deserialization

Let us first define the two terms in Generic form, irrespective of any programming language.

What is Serialization?

Serialization is a process where you convert an Instance of a Class (Object of a class) into a Byte Stream. This Byte
Stream can then be stored as a file on the disk or can also be sent to another computer via the network. Serialization
can also be used to save the sate of Object when the program shuts down or hibernates. Once the state is saved on
disk using Serialization, we can restore the state by DeSerializing the class from disk.

Let us try to visualize this using a small diagram. In this diagram, we will create a small class called Rectangle, which
represents a real-life rectangle. Here is the code for the class

public class Rectangle {

private double height;

private double width;

public Rectangle(double height, double width)

this.height = height;

this.width = width;

public double Area()

return height * width;

public double Perimeter()

return 2 * (height + width);

Note: This class is not yet Serializable as per Java standards, let us ignore it for the time being.
Page | 105
Serialization process on the Rectangle class will look like this.

The encoding scheme that is used to convert from an Object of Class Rectangle to Byte stream is governed by the
Serialization encoding standards mentioned here.

Serializable Interface

In Java, a Serializable object is an object which inherits from either of the two interfaces

• java.io.Serializable

• java.io.Externalizable

Serializable interface is a marker interface. Which means that you do not have to implement any methods if your
class derives from this interface. This is just a marker and the Java runtime, when trying to Serialize the class, will just
check for the presence of this interface in the class. If Serializable interface is present in the class inheritance
hierarchy, Java run time will take care of Serialization of the class.

On the other hand, the Externalizable interface is not a marker interface. If you derive from Externalizable interface
you have to implement these two methods

• readExternal(ObjectInput input)

• writeExternal(ObjectOutput output)

We should inherit from Externalizable interface only when we want to overtake the Java's default serialization
mechanism. If you want to use the default Java's serialization mechanism than you should inherit from Serializable
interface only.

With this understanding, our Rectangle class will now inherit from Serializable interface.

public class Rectangle implements Serializable{

Page | 106
private double height;

private double width;

public Rectangle(double height, double width)

this.height = height;

this.width = width;

public double Area()

return height * width;

public double Perimeter()

return 2 * (height + width);

Serializing an Object in Java

Let us quickly take a look at the Serialization process in Java. In this process, we will perform these four steps

1. We will create a new FileOutputStream of a file where we want to serialize the class

2. We will then ObjectOutputStream on the FileOutputStream created in step 1

3. We will then write the object into the ObjectOutputStream

4. Finally, we will close all the stream objects to save properly write and terminate all streams.

Below is the code to perform the task. Pay attention to the comments that are mentioned above every line of code.

public static void SerializeToFile(Object classObject, String fileName)

try {

// Step 1: Open a file output stream to create a file object on disk.

// This file object will be used to write the serialized bytes of an object

FileOutputStream fileStream = new FileOutputStream(fileName);

Page | 107
// Step 2: Create a ObjectOutputStream, this class takes a files stream.

// This class is responsible for converting the Object of any type into

// a byte stream

ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);

// Step 3: ObjectOutputStream.writeObject method takes an Object and

// converts it into a ByteStream. Then it writes the Byte stream into

// the file using the File stream that we created in step 1.

objectStream.writeObject(classObject);

// Step 4: Gracefully close the streams

objectStream.close();

fileStream.close();

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

public static void main(String[] args)

Rectangle rect = new Rectangle(18, 78);

SerializeToFile(rect, "rectSerialized");

When we run this program, it creates a file named "rectSerialized" in the root folder of the project. Just browse to
that location and try to open the file using a notepad. Below image shows that

Page | 108
When you open this file you can see that it contains garbled characters. The contents are encoded and are not in
human readable format. As shown in the image below.

This shows what exactly serialization means and how we can serialize an object in Java. This should also give you a
practical understanding of the different steps involved in serialization process including the input and output results
of the different steps.

Deserializing to an Object in Java

In the previous section, we learnt the Serialization converts a class instance into a byte stream which is then stored
in a file on disk. Let us quickly take a look at the Deserialization process in Java, which is opposite of Serialization. In
this process, we will read the Serialized byte stream from the file and convert it back into the Class instance
representation. Here are the steps that we will follow.

1. We will create a new FileInputStream to read the file which contains the serialized byte stream of the target
class. Rectangle class in our case.

2. We will then create an ObjectInputStream on the FileInputStream created in step 1

3. We will then read the object using ObjectInputStream and store it in a variable of type Rectangle.

4. Finally, we will close all the stream objects to save properly write and terminate all streams.

Below is the code to perform the task. Pay attention to the comments that are mentioned above every line of code.

public static Object DeSerializeFromFileToObject(String fileName)

try {

// Step 1: Create a file input stream to read the serialized content

// of rectangle class from the file

FileInputStream fileStream = new FileInputStream(new File(fileName));

Page | 109
// Step 2: Create an object stream from the file stream. So that the content

// of the file is converted to the Rectangle Object instance

ObjectInputStream objectStream = new ObjectInputStream(fileStream);

// Step 3: Read the content of the stream and convert it into object

Object deserializeObject = objectStream.readObject();

// Step 4: Close all the resources

objectStream.close();

fileStream.close();

// return the deserialized object

return deserializeObject;

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

return null;

public static void main(String[] args)

Rectangle rect = new Rectangle(18, 78);

SerializeToFile(rect, "rectSerialized");

Rectangle deSerializedRect = (Rectangle) DeSerializeFromFileToObject("rectSerialized");


Page | 110
System.out.println("Rect area is " + deSerializedRect.Area());

Just to verify that the original state of the Rectangle class is restored, we will debug the code and
inspect deSerializedRect variable. The below image shows that the original state of (Height: 18 and Width: 78)
Rectangle class is restored.

I hope that this tutorial clears the basic concept of Serialization and Deserialization in Java for you.

Deserialize JSON Response using Rest Assured


JSON is an extremely popular format when it comes to APIs. Almost all of the APIs either transfer data in the XML
format or JSON format of which JSON is a popular one. Not only through APIs, but the companies also use JSON to
transfer data between their own server to UI because of its lightweight and easily readable features. As a
professional tester or a developer, it will be rare if you do not come across a JSON file and verify its legibility. To
work with them, you should know how to read them through code and make use of automation testing to
accomplish your tasks easily. In this article, we'll discuss the same concept used in the body of the REST Response.
This technique to read the JSON Response is also termed as to "Deserialize" the JSON Response.

Serialization and Deserialization are programming techniques where we convert Objects to Byte Streams and
from Byte Streams back to Objects respectively. We have already discussed this technique in the article Serialization
and Deserialization in Java. We will now cover the following topics in this article:

• What is Serializing a JSON?

• What is Deserializing of a JSON Response?

• How to Deserialize JSON Response to Class with Rest Assured?'

• How to Deserialize JSON Response Body based on Response Status?

What is Serializing a JSON?

Serialization, as mentioned above, is a process of converting data objects into a stream of data. The reverse process
of serialization (stream to object) is deserialization. Both the processes are platform-independent. This means we
can serialize an object on a Windows platform and deserialize it on macOS.

As far as rest assured is concerned, we are aware that the data exchange between client and server takes place in
JSON format by REST web service. The stream of data here is JSON data.

For example, if we have the following object:

{tools: [1, 3, 7, 9], api: "QA"}

when the above object is serialized into JSON, the output will look like the one shown below:

Page | 111
"tools":[1, 3, 7, 9],

"api":"QA"

The above data string can be stored or transferred anywhere. The recipient will then deserialize the data back to its
original format ie object.

Java POJO classes are one way we can serialize the objects and use them in Rest Assured. The details of
implementation are beyond the scope of this tutorial. Serialization is discussed in our previous tutorial Serialization
and Deserialization in Java. While working in the testing industry, we will be more concerned about deserialization.
The same is discussed in the next section in detail.

What is Deserializing a JSON Response?

Before going ahead, it is recommended to read the article REST Api testing in Rest-Assured and converse yourself
with REST, API testing, REST Assured and other similar concepts.

In REST APIs, the process of deserialization is performed especially for the JSON responses we receive from the API.
So, when we say we are deserializing the JSON, this means we convert the JSON format into a type we prefer, most
frequently POJO (Plain Old Java Object) classes.

So in this process, we essentially tell our code to use strongly typed strings that are less error-prone instead of JSON
strings. Let's go ahead and see practically how to deserialize the JSON responses to class with Rest Assured.

How to Deserialize JSON Response to Class with Rest Assured?

We will continue from our example in Making a POST request using Rest-Assured to implement deserialization of
JSON responses. In this article, we have seen that a successful post request sends the following response:

"SuccessCode": "OPERATION_SUCCESS",

"Message": "Operation completed successfully"

In the POST request example, we have used JSONPath to validate the response body parts. Now we have to convert
this response body to a Java class (POJO). In other words, we'll convert the JSON which is a string form to a class
form i.e. deserialize JSON.

Note: Deserialization is also called Object Representation of structured data. The structured data here is JSON.

So how do we begin with deserialization?

First and foremost we need to create a class that has all the nodes (or key) of the JSON response. As we are already
aware, the Success response has two nodes:

• SuccessCode

• Message

Both these nodes contain String values. The screenshot below shows the part of the response we receive.

Page | 112
So we have to create a class with two string variables that will represent nodes in the JSON. Given below is the class
code for the same.

@Test

public class JSONSuccessResponse {

// Note: The name should be exactly as the JSON node name

// Variable SuccessCode will contain value of SuccessCode node

public String SuccessCode;

// Variable Message will contain the value of Message node

public String Message;

Now that we have a JSONSuccessResponse class to store all the nodes present in Successful Response, let's
understand how to use Rest-Assured to automatically convert JSON Response Body to the instance of the
JSONSuccessResponse class.

Converting JSON Response Body to JSONSuccessResponse class

The class io.restassured.response.ResponseBody that represents the response in Rest Assured, has a method
called .as(Class<T>). Here, Class<T> is a generic form of any class of type T which is also referred to as template class.
In this case, Class <T> will be JSONSuccessResponse.

Internally, the "as()" method performs two actions:

• Create an instance of JSONSuccessResponse class.

• Copy the JSON node variables to the respective instance variables of the class. For example, the value of
SuccessCode node to the variable SucessCode and value of Message to variable Message.

Given below is the code demonstrating the Response.Body.as(Class<T>) method.

@Test

public void UserRegistrationSuccessful() {

RestAssured.baseURI ="https://demoqa.com";

RequestSpecification request = RestAssured.given();

JSONObject requestParams = new JSONObject();

requestParams.put("UserName", "test_rest");

requestParams.put("Password", "rest@123");

request.body(requestParams.toJSONString());

Response response = request.post("/Account/v1/User");

ResponseBody body = response.getBody();

// Deserialize the Response body into JSONSuccessResponse

JSONSuccessResponse responseBody = body.as(JSONSuccessResponse.class);


Page | 113
// Use the JSONSuccessResponseclass instance to Assert the values of Response.

Assert.assertEquals("OPERATION_SUCCESS", responseBody.SuccessCode);

Assert.assertEquals("Operation completed successfully", responseBody.Message); }

Once we get the value in responseBody variable, we can validate the response as shown in the code below.

// Use the RegistrationSuccessResponse class instance to Assert the values of

// Response.

Assert.assertEquals("OPERATION_SUCCESS", responseBody.SuccessCode);

Assert.assertEquals("Operation completed successfully", responseBody.Message);

In this way, we can apply assertions to validate the response or even pass this response as input to other tests.

How to Deserialize JSON Response Body based on Response Status?

In the previous section, we discussed how to deserialize the JSON in case of a successful response. But in real-time
applications, we can also receive responses that are failures. In such a case, Rest API may return a completely
different response body. One such format of failed response may be as shown below:

"FaultId": "User already exists",

"fault": "FAULT_USER_ALREADY_EXISTS"

If we use the class JSONSuccessResponse to deserialize the above response, it will not work. This is because Rest
Assured will not find the nodes SuccessCode and Message in the response body like in the above section. These two
variables in the class will have values as null.

The solution to this is to maintain another class that will be used for deserializing the failure response. This class will
have the following structure.

public class JSONFailureResponse {

String FaultId;

String fault;

But now that we have two classes, one for a successful response and another for failure, how can we handle both
these in an application?

We can do this using the HTTP Status Code returned by the server. Rest API in this series returns Status Code =
201 in case of success and 200 in case of failure.

So by making use of the status code we can deserialize the response into appropriate POJO classes depending on
success or failure. Below given code is an updated version of the above code and it takes care of success as well as
failure response.

@Test

public void UserRegistrationSuccessful() {

RestAssured.baseURI ="https://demoqa.com";

RequestSpecification request = RestAssured.given();


Page | 114
JSONObject requestParams = new JSONObject();

requestParams.put("UserName", "test_rest");

requestParams.put("Password", "rest@123");

request.body(requestParams.toJSONString());

Response response = request.post("/Account/v1/User");

ResponseBody body = response.getBody();

System.out.println(response.body().asString());

if(response.statusCode() == 200) {

// Deserialize the Response body into JSONFailureResponse

JSONFailureResponse responseBody = body.as(JSONFailureResponse.class);

// Use the JSONFailureResponse class instance to Assert the values of Response.

Assert.assertEquals("User already exists", responseBody.FaultId);

Assert.assertEquals("FAULT_USER_ALREADY_EXISTS", responseBody.fault);

} else if (response.statusCode() == 201) {

// Deserialize the Response body into JSONSuccessResponse

JSONSuccessResponse responseBody = body.as(JSONSuccessResponse.class);

// Use the JSONSuccessResponse class instance to Assert the values of response.

Assert.assertEquals("OPERATION_SUCCESS", responseBody.SuccessCode);

Assert.assertEquals("Operation completed successfully", responseBody.Message);

In the above code, we deserialize the response to JSONSuccessResponse or JSONFailureResponse class depending on
whether the Status code is Success or Failure.

Note: Another way to deserialize multiple responses is by using the inheritance chain which readers can implement as
an exercise.

Authentication and Authorization in REST WebServices


Authentication and Authorization in REST WebServices are two very important concepts in the context of REST API.
The majority of the time you will be hitting REST API's which are secured. By secure, we mean that the APIs which
require you to provide identification. Identification can be provided in the form of

• Username and a Password

• Authentication tokens
Page | 115
• Secret keys

• Bio-metrics and many other ways

In the context of REST API, we will be more interested in the first three options. The Authentication and
Authorization models that we will discuss are spread across multiple tutorials, starting from this tutorial.

What is Authentication? and How does Authorization work in REST WebServices?

Authentication is a process to prove that you are the person you intend to be.

For e.g. while logging into your email account, you prove that you are you by providing a Username and a Password.
If you have the Username and the Password you are who you profess to be. This is what Authentication means.

In the context of REST API authentication happens using the HTTP Request.

Note: Not just REST API, authentication on any application working via HTTP Protocol happens using the HTTP
Request.

Basic Authentication Flow

Taking the example of email login, we know that in order to Authenticate our self we have to provide a username
and a password. In a very basic Authentication flow using Username and Password, we will do the same thing in
REST API call as well. but how do we send the Username and Password in the REST request?

A REST request can have a special header called Authorization Header, this header can contain the credentials
(username and password) in some form. Once a request with Authorization Header is received, the server can
validate the credentials and can let you access the private resources.

Note: I hope from previous tutorials you are able to understand the meaning of a Resource. If not, please go
through this tutorial: Rest architectural elements. A private resource is one that is not accessible to everyone. You
need to Authenticate yourself to access the private resource. For e.g. the email inbox, you have to log in to see the
emails.

Let us see it with an example, we have created an API that needs a valid Username and Password to access the
Resource.

Endpoint: http://restapi.demoqa.com/authentication/CheckForAuthentication

In the code below we will try to hit the URL and see what is the Response that we get.

@Test

public void AuthenticationBasics()

RestAssured.baseURI = "https://restapi.demoqa.com/authentication/CheckForAuthentication";

RequestSpecification request = RestAssured.given();

Response response = request.get();

System.out.println("Status code: " + response.getStatusCode());

System.out.println("Status message " + response.body().asString());

Page | 116
In the code above we are simply making an HTTP GET request to the endpoint. In this code, we have not added
any Authorization header. So the expected behavior is that we will get Authorization error. If you run this test, you
will get the following output.

Status code: 401

Status message:

"StatusID": "FAULT_USER_INVALID_USER_PASSWORD",

"Status": "Invalid or expired Authentication key provided"

The output clearly says that we have "Invalid or expired Authentication key provided" error. This means that either
there was no Authentication information or the information supplied was invalid. Eventually, the server denies our
request and returns an error response.

Note: Pay special attention to the Status code returned. In case of , Authentication failures Server should respond
with a status code of 401 Unauthorized.

Try to hit that URL using a browser. You should get a Username and Password prompt. The below image shows what
you should be getting when you hit this URL from the browser.

In this tutorial, we will not discuss how to pass Authentication information in the Request header. Here we will only
focus on the definitions of Authentication and Authorization. In the next set of tutorials, we will see
different Authentication models, which will solve the above problem.

Page | 117
What is Authorization? and How does Authorization work in REST WebServices?

Authorization is the process of giving access to someone. If you are Authorized then you have access to that
resource. Now to Authorize you to need to present credentials and as we discussed earlier that process is called
Authentication. Hence Authorization and Authentication are closely related terms and often used interchangeably.

Before ending the tutorial let us see the contents of the private resource in the URL mentioned above. To do that
enter the following credentials

• Username: ToolsQA

• Password: TestPassword

The server will be able to Authenticate and then Authorize you to access the private resource content. The below
image shows the content after successful Authentication.

With this basic understanding of Authentication and Authorization, read the coming tutorials where we will discuss
the specif types of Authentication models in REST API.

Basic Authentication
In our series, we have so far covered the basics of Rest Assured, the different types of requests
like POST, PUT and DELETE. In addition, we also covered the basics of Authentication & Authorization concepts of
Rest API. Practically in the projects, as we proceed with automation, we come across complex APIs. These require
basic authentication implementation mixed along with other code. In this article, we will cover the handling of basic
authentication in Rest Assured. We will focus on the below points-

• What is Basic Authentication(Auth)?

• What are the different authentication schemes provided by Rest Assured?

o Basic Authentication in Rest Assured.

▪ Preemptive Authentication.

o Digest Authentication.

o Form Authentication.

o OAuth Authentication.

▪ OAuth1

▪ OAuth2

What is Basic Authentication (Auth)?

While going through the previous tutorials you must have noticed that we have used the username and the
password (authentication credentials) for certain APIs. This credential setting is to enforce access control for the web
resources and is generally passed in the header field of an HTTP request. The implementation of basic authentication
Page | 118
is to ensure that the APIs are secured and only the users who are authorized have the access to view them. Hence,
the authentication information is not encrypted or hashed but encoded as base-64. We will now see the different
schemes used in Rest Assured for authentication and you may go through our previous article on Authentication and
Authorization for more information.

What are the different authentication schemes provided by Rest Assured?

To test and validate any secured API, you will have to use some authentication scheme. Rest Assured provides
several authentication schemes which we are going to discuss in this part.

Before proceeding to understand the use of authentication in Rest Assured, let us execute our Rest Assured test
without using any sort of authentication. Below is the code for your reference-

package org.example;

import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.response.ResponseBody;

import io.restassured.specification.RequestSpecification;

public class BasicAuth {

@Test

public void getData() {

RequestSpecification httpRequest = RestAssured.given();

Response res = httpRequest.get("https://postman-echo.com/basic-auth");

ResponseBody body = res.body();

//Converting the response body to string

String rbdy = body.asString();

System.out.println("Data from the GET API- "+rbdy);

The code is pretty simple and uses the get () method to send requests to the server. Do not worry if you don't
understand. It will be explained in the later examples. On executing this code the result would be-

Page | 119
Observe the message in the first line - "Data from the GET API - Unauthorized". This is the issue that we are going to
fix using the basic authentication in our rest assured tests. Let us quickly jump on to understanding the same.

Basic Authentication in Rest Assured

As discussed above, the basic authentication scheme uses the username and password in base64 encoded format.
The request header needs to contain the credentials of the user for access to the resource. It is very easy to send the
credentials using the basic auth and you may use the below syntax-

given().auth().basic("your username", "your password").get("your end point URL");

In the given method you need to append the method of authentication specification followed by the basic HTTP auth
where you will pass the credentials as the parameters. Another type of basic authentication is preemptive which we
will discuss next.

package org.example;

import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.response.ResponseBody;

import io.restassured.specification.RequestSpecification;

public class BasicAuth {

@Test

public void getData() {

RequestSpecification httpRequest = RestAssured.given().auth().basic("postman", "password");

Response res = httpRequest.get("https://postman-echo.com/basic-auth");

ResponseBody body = res.body();

//Converting the response body to string

String rbdy = body.asString();

System.out.println("Data from the GET API- "+rbdy);

Preemptive Authentication

By default, Rest Assured uses the challenge-response mechanism. This means that it waits for the server to
challenge rather than send the credentials directly. By using the preemptive directives we can avoid that additional
call that the server makes and hence additional complications. In a way, it is similar to the basic auth we saw above,
the only difference is that an additional premptive () directive adds after auth (). Let us see its syntax followed by a
working code example.

given().auth().preemptive().basic("your username", "your password").get("your end point URL");


Page | 120
As you may see above, the preemptive authentication view sends the authentication details in the request header
irrespective of being asked by the server. In the same line of implementation, we will see a simple API that uses
preemptive authentication.

package org.example;

import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.response.ResponseBody;

import io.restassured.specification.RequestSpecification;

public class BasicAuth {

@Test

public void getUserData() {

//Using the preemptive directive of basic auth to send credentials to the server

RequestSpecification httpRequest = RestAssured.given().auth().preemptive().basic("postman", "password");

Response res = httpRequest.get("https://postman-echo.com/basic-auth");

ResponseBody body = res.body();

//Converting the response body to string

String rbdy = body.asString();

System.out.println("Data from the GET API- "+rbdy);

The code example used above is a simple Get API where we are trying to fetch the details corresponding to the user.
Note that the server needs the authentication details of the user to get a successful response. Let us glide through
the code line-by-line.

RequestSpecification httpRequest = RestAssured.given().auth().preemptive().basic("postman", "password");

An object of RequestSpecification is created and using the preemptive directive the credentials of the user are sent
in the header. Note that irrespective of being asked for the credentials these would be passed to the server.

Response res = httpRequest.get("https://postman-echo.com/basic-auth");

ResponseBody body = res.body();

The endpoint URL is accessed using the get method and the response is saved using the ResponseBody object.

String rbdy = body.asString();

System.out.println("Data from the GET API- "+rbdy);

Finally, we convert the response body to string and print the result. Similarly, you may add additional validations as
per your requirements.
Page | 121
Console prints the response of the above code without errors.

And there you go! You have successfully retrieved the user data by simply adding the preemptive authentication in
your code and passing the credentials.

Digest Authentication

It is somewhat similar to challenge-based authentication but is more secure as it uses a digestive key in subsequent
requests. If at all it is intercepted by an eavesdropper, he will get access only to the transaction performed and not
the user password. The transaction might be replayed but a new transaction cannot be made as the password is not
exposed. Its syntax is similar to basic authentication-

given().auth().digest("your username", "your password").get("your end point URL")

Note that we cannot use the preemptive () similar to basic auth since this scheme uses only challenged
authentication.

Form Authentication

There can be many cases when you need to pass the authentication credentials in an HTML form. This request is
generally sent as a post method where the credentials entered in the form are used for authentication. So, if your
application uses such a form-based authentication you can easily automate it using the form() scheme. The syntax
for it follows-

given ().auth ().digest ("your username", "your password").get ("your endpoint URL")

given() .auth().form("your username", "your password").post("your end point URL")

If you use this approach then Rest Assured will first have to parse through the HTML response to find the fields for
input and then send the form parameters. However, there is a high possibility that this approach might fail if the
webpage is complex. Additionally, it would also fail if the context path is not included in the action attribute of the
service. To optimize it to handle such cases, you may use the below format where you explicitly pass the required
fields by providing the FormAuthConfig()-

given().auth().form("your username", "your password", new FormAuthConfig("/perform_signIn","user","password"))

OAuth Authentication

Another type of authentication is OAuth authentication. OAuth is an authorization framework that defines an
identity protocol. It has wide usage in web applications and there are high chances that you will have to automate
those authentication actions. These can be of two types viz, OAuth 1.0 and OAuth 2.0 which we will discuss now.

OAuth 1.0

Secured resources built using OAuth 1.0 requires passing consumer key, secret, access token, and token secret. The
syntax it follows is -

given().auth().oauth(consumerKey, consumerSecret, accessToken, tokenSecret).get("your end point URL")

OAuth parameters read the required user input dynamically.

OAuth 2.0

Page | 122
There are cases when we need to generate an access token for a user session. This access token performs various
transactions and helps maintain the user session. While using OAuth 2.0 you need to directly pass the access token
generated when the user login using the below syntax-

given().auth().oauth2("Access token").get("your end point URL")

Using the access token you can easily request any of the resources secured using the OAuth scheme.

Now you may identify the types of authentication used in your web application. Similarly, you can use the
corresponding authentication scheme to make full use of rest assured capabilities.

PUT Request using Rest Assured


In earlier articles, we have seen how to read various components of an *HTTP Response (Headers,Body, and
Status) and to Post a request* using Rest Assured. In this article, we will continue our exploration of HTTP request
methods and move on to the next method - the PUT request method using REST Assured.

• What is an HTTP PUT Request Method?

• PUT Vs. POST Request.

o Status codes were obtained for PUT and POST requests.

o REST API example.

• How to implement a PUT Request using Rest Assured?

o Create JSON data using Simple JSON library.

o Send JSON content in the body of the Request.

o Validate the Response.

What is an HTTP PUT Request Method?

The *PUT method *(HTTP PUT request method) creates a new resource or updates (substitutes) a representation of
the target resource with the request payload. This means a Put request updates a resource at a specified URI. It is
also used to create a new resource at the given URI or replace the entire product entity.

The official HTTP RFC specifies:

• A PUT method puts or places a file or resource precisely at a specific URI.

o In case a file or a resource already exists at that URI, the PUT method replaces that file or resource.

o If there is no file or resource, PUT creates a new one.

• Responses to the PUT method are non-cacheable.

• PUT requests usually respond back with status code 200.

PUT Vs. POST Request

Let us now discuss the main differences between a PUT and a POST request.

PUT POST

This method is idempotent. This means it will produce the This method is not idempotent. It produces different
same results if executed more than once. results every time it is executed.

When we need to modify a single resource that is already POST method is called when a child resource is to be
part of resource collection, we call the PUT method. added under resources collection.

Page | 123
PUT POST

PUT method syntax : PUT /questions/{question-id} POST method syntax: POST /questions

PUT works as specific. POST works as abstract.

Put method makes use of the "UPDATE" query. POST method makes use of the "CREATE" query.

In the PUT method, the client decides which URI resource In the POST method, the server decides which URI
should have. resource should have.

POST /vi/cake/orders* indicate that we are creating a


*PUT /vi/cake/orders/1234 indicates updation of a resource
new resource and return an identifier to describe the
identified by "1234".
resource.

Status codes obtained for PUT and POST requests

The methods POST and PUT use the following status codes:

POST request

• 201 with a location header pointing to the new resource.

• 400 if the new item is not created.

PUT request

• 204 for OK/SUCCESS (but no content).

• 200 for OK with Content Body (Updated response).

• 400 if the data sent was invalid.

REST API example

Now we'll demonstrate the PUT request using Swagger UI. The URL for the PUT request is given
here https://demoqa.com/BookStore/v1/Books/

Also, you can take a look at the Book Store Swagger

When we access this URL, we get the following screen.

Page | 124
In the above screen, we a trying to update a book record with ISBN="9781449325862". The two parameters that we
will update are userId: "toolsqa_test" and ISBN: "9781449325865". When we execute this put request we get the
following output.

We can see the status code 200 which we received from the server indicating the request was successful.

In the next section, we will implement the PUT request using Rest Assured.

How to implement a PUT Request using Rest Assured?

As explained in the tutorial on a *POST request, to create JSON objects, we will add a Simple JSON* library in the
classpath in the code. Once this is done, we follow the below-given steps to put a request using REST Assured.

• Create JSON data using a simple JSON library.

• Send JSON content in the body of the request.

• Validate the response.

Let us discuss each of these steps below.

Create JSON data using Simple JSON library

We will use the same URL for implementing the PUT request using Rest Assured.

Endpoint: https://demoqa.com/BookStore/v1/Books/

The first step is to create a JSON data request that we need to send using the "put()" method. The following piece of
code achieves this.

java import io.restassured.RestAssured; import io.restassured.specification.RequestSpecification; import


org.junit.Test;

public class PUTMethod { @Test public void putMethod() {

String userId = "toolsqa_test";

String baseUrl = "https://demoqa.com";

String token =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6InRlc3RpbmcxMjMiLCJwYXNzd29yZCI6IlBhc3N3b3JkQDEiL
CJpYXQiOjE2Mjg1NjQyMjF9.lW8JJvJF7jKebbqPiHOBGtCAus8D9Nv1BK6IoIIMJQ4";

Page | 125
String isbn = "9781449325865";

RequestSpecification httpRequest = RestAssured.given().header("Authorization", "Bearer " +


token).header("Content-Type", "application/json");

In the above code, we have used an ISBN parameter. Note that we already have a record with this ISBN. We will
update this record by sending the PUT request. So for this ISBN, we will update the record with a new ISBN and a
userId. We set a new value for the ISBN and also updated userId. So when we send this request, the record having
ISBN="9781449325862" will have its userId="toolsqa_test" and ISBN updated to the new value, "9781449325865".

Send JSON content in the body of the Request

The generated request is sent to the server.

java Response res = httpRequest.body("{ "isbn": "" + isbn + "", "userId": "" + userId + ""}")

.put("/BookStore/v1/Book/9781449325862");

So in the above code, we have created a request body as a JSON string and then we call the "put()" method with this
request by sending the ISBN as an argument. This ensures the record with the given ISBN is updated.

Validate the Response

The next step is to validate the response to ensure record updation. This is done by reading the status code of the
response as follows:

java //validate the response System.out.println("The response code - " +res.getStatusCode());

Assert.assertEquals(res.getStatusCode(),200);

We have used the getStatusCode () method that returns the status code of the response. The value 200 indicates the
PUT request was successful. The execution of the above tests gives the following response:

We see that the test case has passed.

The complete code for the PUT request demonstration using Rest Assured is as follows:

java package org.example;

import io.restassured.RestAssured; import io.restassured.specification.RequestSpecification; import org.junit.Assert;


import org.junit.Test; import io.restassured.response.Response; import io.restassured.response.ResponseBody;
import io.restassured.specification.RequestSpecification; import org.testng.annotations.AfterTest; import
org.testng.annotations.BeforeTest;

public class PUTMethod { String userId= "toolsqa_test"; String baseUrl="https://demoqa.com"; String token =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6InRlc3RpbmcxMjMiLCJwYXNzd29yZCI6IlBhc3N3b3JkQDEiL
CJpYXQiOjE2Mjg1NjQyMjF9.lW8JJvJF7jKebbqPiHOBGtCAus8D9Nv1BK6IoIIMJQ4"; String isbn ="9781449325865";

@Test
Page | 126
public void updateBook() {

RestAssured.baseURI = baseUrl;

RequestSpecification httpRequest = RestAssured.given().header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

//Calling the Delete API with request body

Response res = httpRequest.body("{ \"isbn\": \"" + isbn + "\", \"userId\": \"" + userId +
"\"}").put("/BookStore/v1/Book/9781449325862");

//Fetching the response code from the request and validating the same

System.out.println("The response code - " +res.getStatusCode());

Assert.assertEquals(res.getStatusCode(),200);

The steps discussed above demonstrate the basic working of a PUT request and how it differs from a POST request.
We used the JSON library to create JSON data sent in the content of the body of the request. We then validate the
response using the status code after obtaining the response.

DELETE Request using Rest Assured


APIs form the base for any application and in every application, you perform a lot of different actions. These actions
may range from adding, viewing, editing or deleting data. Since we have so many actions, we have to have a variety
of tests to test the correctness of these actions. In our previous post, we learnt how to perform PUT requests using
Rest Assured, and in this post, we will learn about the HTTP DELETE request method using the same method. If you
have not gone through our previous articles I would urge you to go through our Rest Assured series step-by-step to
understand the basics.

In this article, we will cover the below point-

• What is a Delete request?

• What are the different response codes for Delete Request?

• How to make a Delete Request using Rest Assured?

What is a delete request method?

An HTTP delete request is performed using the HTTP delete method (written as delete) which deletes a resource
from the server identified by the URI we are sending through it. Also note that a delete method intends to change
the state of the server. Although even a 200 code does not guarantee this. A few major points as highlighted in the
official HTTP RFC with respect to the delete request method are listed below-

• The Delete method requests the server to delete the resource identified by the request URI.

• The resource deletion depends on the server and is deleted if prescribed for deletion. Additionally, the
restoration implementation of the resource is also considerable.

• There is a deletion request for association between the resource and corresponding current functionality.

Page | 127
• It is similar to the rm UNIX command, where the current association of the resource is deleted instead of the
previous ones(if any).

• Delete request method is placed under the idempotent category of the W3C documentation. It means that
once a resource is requested for deletion, a request on the same resource again would give the same result as
the resource has already been deleted.

• Delete method response is non-cacheable. The user cannot cache the server response for later use. Caching a
delete request creates inconsistencies.

Let's see the response code of Delete request now.

What are the different response codes for Delete Request?

On sending the Delete request, the server responds with some response codes which signify the action performed by
the Delete method. Consider the following code for the same-

• 202(Accepted): The server accepts the request but does not enact.

• 204(No Content)- A status code of 204 on the HTTP delete request method denotes successful enactment of
the delete request without any content in the response.

• 200(OK)- The action was successful and the response message includes representation with the status.

• 404(Not Found) - When the server can't find the resource. The reason could either does not exist or previously
deleted.

Now that we understand the basics of the Delete method we will see how we can send a Delete request using rest
assured but before that let us see a simple DELETE request using Swagger UI. The URL for the request is-

https://demoqa.com/swagger/

The URL will show a screen like below-

Now you will have to select the first "Delete" in the BookStore section from this page.

Page | 128
Note: We have disabled the UserID to prevent an empty database. In practical application, you have to pass the
required values to the server.

When you will click on the section, you will see a response depicting that the execution was a success. A specific
response is received for cases like "bookid not found" or "user not found". See the snapshot below for more clarity-

In the introduction, we defined the delete method as something that can delete a resource. As a reminder, you can
relate the "resource" with the pet record here. A generic term "resource" denotes varying resources in various
requests. Now that we have seen how we may go about manually deleting a resource using swagger next we will try
to automate the Delete request using Rest Assured.

How to make a Delete Request using Rest Assured?

We will now see how we can delete a resource from the server using rest assured. To do so, we will use BookStore
APIs which we have been using in our previous examples. We will be automating the following use case-

1. Get a list of available books for to a user using the Get User Data API.

2. Delete a book corresponding to a specific ISBN and validate the response code using the Delete Book API.

3. Verify that the execution of API from step 1 updates the book list and does not display the deleted book.

Let us now see the code for the above use case using Rest Assured.

package bookstore;

import org.testng.Assert;

import org.testng.annotations.AfterTest;

import org.testng.annotations.BeforeTest;

import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.response.ResponseBody;

import io.restassured.specification.RequestSpecification;

public class DeleteBook {

Page | 129
String userId= "de5d75d1-59b4-487e-b632-f18bc0665c0d";

String baseUrl="https://demoqa.com/swagger/";

String token =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6InRlc3RpbmcxMjMiLCJwYXNzd29yZCI6IlBhc3N3b3JkQDEiL
CJpYXQiOjE2Mjg1NjQyMjF9.lW8JJvJF7jKebbqPiHOBGtCAus8D9Nv1BK6IoIIMJQ4";

String isbn ="9781449337711";

@BeforeTest

@AfterTest

public void getUserData() {

RestAssured.baseURI = baseUrl;

RequestSpecification httpRequest =

RestAssured.given().header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

Response res = httpRequest.get("/Account/v1/User/"+userId);

ResponseBody body = res.body();

//Converting the response body to string

String rbdy = body.asString();

System.out.println("Data from the GET API- "+rbdy);

@Test

public void deleteBook() {

RestAssured.baseURI = baseUrl;

RequestSpecification httpRequest = RestAssured.given().header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

//Calling the Delete API with request body

Response res = httpRequest.body("{ \"isbn\": \"" + isbn + "\", \"userId\": \"" + userId +
"\"}").delete("/BookStore/v1/Book");

//Fetching the response code from the request and validating the same

System.out.println("The response code is - " +res.getStatusCode());

Assert.assertEquals(res.getStatusCode(),204); }

}
Page | 130
Code walkthrough

Let's walk through the above code and see what we tried to achieve here. Note that the first method, i.e
getUserData() is a simple GET method where we are trying to fetch the user data corresponding to a userId. You may
refer to our article on Rest API using Rest Assured to understand the code if you have not gone through it yet.
Additionally, you will notice the authorization field. For this particular tutorial on the delete request method, you
need not worry about it. However, if you want to learn about authorization and OAuth 2.0, you can refer to our
other tutorials. In this tutorial about the delete method, we will go through the code written
under deleteBook() method here.

RestAssured.baseURI = baseUrl;

RequestSpecification httpRequest = RestAssured.given().header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

We first set up the request with the base URI. Next, we add the header(s) which also include the Authorization token
using the RequestSpecification interface.

Response res = httpRequest.body("{ \"isbn\": \"" + isbn + "\", \"userId\": \"" + userId +
"\"}").delete("/BookStore/v1/Book");

Next, store the Response object using the RequestSpecification object. Here we are passing the JSON body of our
request along with the endpoint URL for the Delete method. The response gets store in a variable.

System.out.println("The response code is - " +res.getStatusCode());

Assert.assertEquals(res.getStatusCode(),204);

Lastly, we are simply printing the response status code and using the TestNG Assert to validate the same. Since in
our case the expected response code is 204, our test would have it as the expected parameter.

Once you execute the code you will see that the getUserData method executes first, followed by the deleteBook
method. And then finally the getUserData method runs again. This is because we used
the @BeforeTest and @AfterTest for the getUserData method. The console would show you the result as below-

And there you go! You have successfully deleted a record from the user data using the Delete API. Now you may go
ahead and try out the different API methods using Rest Assured and strengthen your concepts. In our next post, we
will see how Basic Auth handles Rest Assured.

Page | 131
What is JSON?
JSON is one of the most used Data-Exchange format. It is a light weight format represented as pure text. Due to the
ability of almost all the languages to parse text, Json becomes independent of the programming language.

What is JSON?

JSON stands for JavaScript Object Notation. JSON is a human and machine-readable format to represent data
as Structured Data. JSON is used primarily to transfer data from one computer to another or even between different
programs on the same computer.

To visualize JSON, let us say that we want to represent a Person with following details in JSON

• First Name = Virender

• Last Name = Singh

• Age = 34

• Profession = Engineer

In JSON , this will turn out to be

"FirstName" : "Virender",

"LastName" : "Singh",

"Age" : 34,

"Profession": "Engineer"

At this point, we do not know the details of the JSON structure but we can still figure out what is being presented
in JSON . Let us now understand different elements used in JSON .

Note: It is always beneficial to represent Keys without spaces in the name.

Key-Value Pairs

Key-Value pairs in JSON are used to represent a property of the Object. In the above example, we tried to represent
a Person. This person has some properties like

• First Name

• Last Name

• Age

• Profession

Each of these properties have a value associated with it. For e.g First Name has a value of Virender.
Similarly, Age has a value of 34. To write a Key-Value in JSON we have to follow these rules

• Key-value pairs are separated by a : (colon)

• Key is always present in Double Quotes " "

• Value could be anything depending on the Data Type

From the above example, a Key-Value pair is FirstName. Try to find other Key-Value pairs yourself

"FirstName" : "Virender"
Page | 132
Values can be of following data types

• Boolean: True or False

• Number: Numerical values

• Object: An associative array of Key-Value pairs

• Array: Associative array of just values

Object in JSON

In JSON an object is represented by a collection of Key-Value pairs. This collection of Key-Value pairs are grouped
using { } (opening and closing curly braces}. Rules to writing an Object are

• Key-Value pairs should be separated by a , (Comma)

• Each Object should Start with an Opening { (Opening Curly Brace)

• Each Object should End with a Closing } (Closing Curly Brace)

An example here is the Person Object, discussed above. The Person object follows the rules mentioned for
representing an Object

"FirstName" : "Virender",

"LastName" : "Singh",

"Age" : 34,

"Profession": "Engineer"

Array in JSON

Arrays are similar to Arrays that you know from any other programming language. In JSON an Array is collection of
Values separated by Comma. Here are the rules to write an Array

• An Array starts with an opening [ (Bracket)

• An Array ends with a closing ] (Bracket)

• Values in the Array are separated by , (Comma)

To understand an Array let us add one more property to the Person Object. Let us add hobby also, a Person can have
multiple hobbies. This makes it suitable to represent hobbies as an Array. As shown in the JSON below

"FirstName" : "Virender",

"LastName" : "Singh",

"Age" : 34,

"Profession": "Engineer",

"Hobbies" : ["Videos games", "Computers", "Music"]

Page | 133
See how multiple hobbies are represented using an Array. Array starts and ends with [ ] and contains values
separated by ,

These are the different components of a JSON , using these components we can create complex JSON . As a small
exercise for you, try to decode the JSON below and identify different structures involved in it.

"Description": "Map containing Country, Capital, Currency, and some States of that Country",

"Region": "Asia",

"Countries": [

"Country": "India",

"Data": {

"Capital": "New Delhi",

"minimum temp (Degree Celsius)": 6,

"maximum temp (Degree Celsius)": 45,

"Currency": "Rupee"

},

"Country": "Nepal",

"Data": {

"Capital": "Katmandu",

"minimum temp (Degree Celsius)": 9,

"maximum temp (Degree Celsius)": 23,

"Currency": "Nepalese rupee"

JSONPath and Query JSON using JSONPath


One of the most important advantage of JSON is that it is a light weight format that can be used to interchange data
between computers and processes. JSON , like XML, is a format to provide structure to the data. If you are not
familiar with JSON, please go through this tutorial first of Introduction to JSON.

In this tutorial, we will learn more about JSONPath and Query JSON using JSONPath. We will be covering the
following topic:

• What is JSONPath?

Page | 134
• How to Query JSON with JSONPath?

• Different strategies to query JSON object and JSON Array.

What is JSONPath?

Every JSON object is composed on an inherent hierarchy and structure. Every JSON ends up creating a tree of nodes,
where each node is a JSON Element. Let us take an example here, below is a simple JSON expressing a collection of
countries

"Description": "Map containing Country, Capital, Currency, and some States of that Country",

"Region": "Asia",

"Countries": [

"Country": "India",

"Data": {

"Capital": "New Delhi",

"mintemp": 6,

"maxtemp": 45,

"Currency": "Rupee"

},

"Country": "Nepal",

"Data": {

"Capital": "Katmandu",

"mintemp": 9,

"maxtemp": 23,

"Currency": "Nepalese rupee"

At the top most level we have a Root node, which is basically the node containing all of the current JSON. Inside this
root node, we have following nodes

• Description

• Region


Countries
Page | 135
Description and Region are simple leaf nodes in the tree. But Countries is a non-leaf node, which further contains
more nodes. Here Countries node contains an array of two countries. If we were to simply define a hierarchical
relation between the Root node and any node in the JSON we can do like shown below.

Note: Let us represent Root node by $ and a relationship from parent to child with >>

Description node will be represented by $ >> Description.

Region node will be represented by $ >> Region.

Similarly, we can also define a relationship between the Root node and the zero'th item in the Countries array.
Relationship will be $ >> Countries[0] where [ ] is the index operator to represent an item at n index in an Array
of Countries.

In a way this hierarchy in JSON allows us to create a standard mechanism to traverse through specific parts of
the JSON. A standard way to do this is called JSONPath.

How to Query JSON using JSONPath?

JSONPath creates a uniform standard and syntax to define different parts of a JSON document. JSONPath defines
expressions to traverse through a JSON document to reach to a subset of the JSON. This topic is best understood by
seeing it in action. We have created a web page which can help you evaluate a JSONPath. Use this page to practice
writing JSONPath. This is the link to JSONPath evaluator.

Get Root node operator in JsonPath

Root node operator in JSON is represented by a $ sign. $ will return all the nodes inside the JSON document. To try
this out open the JSONPath evaluator page and type $ in the JSONPath field. As shown in the image below

Get Children operator in JSONPath

In order to get children of a given node, we can use the Dot (.) operator or the ['childname'] operator. In order to
get all the Countries we can have JSONPath as

Page | 136
• $.Countries

• $['Countries']

Output will be

"Country": "India",

"Data": {

"Capital": "New Delhi",

"mintemp": 6,

"maxtemp": 45,

"Currency": "Rupee"

},

"Country": "Nepal",

"Data": {

"Capital": "Katmandu",

"mintemp": 9,

"maxtemp": 23,

"Currency": "Nepalese rupee"

Wildcard operator in JSONPath

Wild card operator in JSONPath is (Star or Asterisk) symbol. This is literally means everything under that node. For
example, if you want to display the Data nodes of all the countries you can simple write following JSONPat

• $.Countries[].Data*

• $['Countries'][].Data*

This will display the Data nodes of all the countries

"Capital": "New Delhi",

Page | 137
"mintemp": 6,

"maxtemp": 45,

"Currency": "Rupee"

},

"Capital": "Katmandu",

"mintemp": 9,

"maxtemp": 23,

"Currency": "Nepalese rupee"

Array Index operator in JSONPath

Sometimes it is required to access a particular entry at a given index in the JSON array. We can use the Array
Index [i,j,k... ] to identify an entry at a particular index. In the above example, let us find out the last Country entry
in the Countries array.

• $.Countries[-1]

• $['Countries'][-1]

Here -1 stands for the last item in the Array. You can also refer to the last item by giving a positive value to the index.
For e.g.

• $.Countries[1]

• $['Countries'][1]

Output will look like this

"Country": "Nepal",

"Data": {

"Capital": "Katmandu",

"mintemp": 9,

"maxtemp": 23,

"Currency": "Nepalese rupee"

Note: Array index starts from 0. Hence to refer to the second item in the array we have to use 1 as the index.

Page | 138
Array index is just not limited to displaying only 1 item. We can extract multiple items from the array at different
indexes. The syntax to do so is [i,j,k..]. For e.g. to extract the first 2 array items we will write the JSONPath as

• $.Countries[0,1]

• $['Countries'][0,1]

Output will be

"Country": "India",

"Data": {

"Capital": "New Delhi",

"mintemp": 6,

"maxtemp": 45,

"Currency": "Rupee"

},

"Country": "Nepal",

"Data": {

"Capital": "Katmandu",

"mintemp": 9,

"maxtemp": 23,

"Currency": "Nepalese rupee"

For the JsonPath shown below, we will change our Json to have more nodes. Let us take a look at
a Json representing collections of books. Here is the Json, from now on use this Json in the JsonPath Evaluator

"store": {

"book": [

"category": "reference",

"author": "Nigel Rees",

"title": "Sayings of the Century",

Page | 139
"price": 8.95

},

"category": "fiction",

"author": "Evelyn Waugh",

"title": "Sword of Honour",

"price": 12.99

},

"category": "fiction",

"author": "Herman Melville",

"title": "Moby Dick",

"isbn": "0-553-21311-3",

"price": 8.99

},

"category": "fiction",

"author": "J. R. R. Tolkien",

"title": "The Lord of the Rings",

"isbn": "0-395-19395-8",

"price": 22.99

],

"bicycle": {

"color": "red",

"price": 19.95

},

"expensive": 10

Array slice operator in JsonPath

Array slice operator is wonderful operator to extract selected items from Json. Taking the example of books, what if
we want to retrieve every alternative book in the Json. To do that we will need the Array, Slice operator. Syntax of
Array Slice operator is [StartIndex : EndIndex : Steps]. Let find out what are books at odd number in the books
collection. JsonPath will look like
Page | 140
• $..book[1,4,2]

• $..['book'][1,4,2]

the output of the above JsonPath will be

"category": "fiction",

"author": "Evelyn Waugh",

"title": "Sword of Honour",

"price": 12.99

},

"category": "fiction",

"author": "Herman Melville",

"title": "Moby Dick",

"isbn": "0-553-21311-3",

"price": 8.99

Expressions in JSONPath
Usage of Expressions in JsonPath is a very good feature to have concise and complex JsonPaths. Expressions in
JsonPath are basically code snippets that evaluate to the Boolean value. Based on the outcome only the nodes which
meet the criteria are selected. Let us see more about it, but before that make sure you have gone through following
tutorials on basics of Json and JsonPath

• Json

• Jsonpath

In this tutorial, we will use a sample Json which has a few items in the Array. Please copy the below Json in
our JsonPath Evaluator

"books": [

"isbn": "9781593275846",

"title": "Eloquent JavaScript, Second Edition",

"subtitle": "A Modern Introduction to Programming",

"author": "Marijn Haverbeke",

"published": "2014-12-14T00:00:00.000Z",
Page | 141
"publisher": "No Starch Press",

"pages": 472,

"description": "JavaScript lies at the heart of almost every modern web application, from social apps to the
newest browser-based games. Though simple for beginners to pick up and play with, JavaScript is a flexible, complex
language that you can use to build full-scale applications.",

"website": "https://eloquentjavascript.net/"

},

"isbn": "9781449331818",

"title": "Learning JavaScript Design Patterns",

"subtitle": "A JavaScript and jQuery Developer's Guide",

"author": "Addy Osmani",

"published": "2012-07-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 254,

"description": "With Learning JavaScript Design Patterns, you'll learn how to write beautiful, structured, and
maintainable JavaScript by applying classical and modern design patterns to the language. If you want to keep your
code efficient, more manageable, and up-to-date with the latest best practices, this book is for you.",

"website": "https://www.addyosmani.com/resources/essentialjsdesignpatterns/book/"

},

"isbn": "9781449365035",

"title": "Speaking JavaScript",

"subtitle": "An In-Depth Guide for Programmers",

"author": "Axel Rauschmayer",

"published": "2014-02-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 460,

"description": "Like it or not, JavaScript is everywhere these days-from browser to server to mobile-and now you,
too, need to learn the language or dive deeper than you have. This concise book guides you into and through
JavaScript, written by a veteran programmer who once found himself in the same position.",

"website": "https://speakingjs.com/"

},

"isbn": "9781491950296",

"title": "Programming JavaScript Applications",


Page | 142
"subtitle": "Robust Web Architecture with Node, HTML5, and Modern JS Libraries",

"author": "Eric Elliott",

"published": "2014-07-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 254,

"description": "Take advantage of JavaScript's power to build robust web-scale or enterprise applications that are
easy to extend and maintain. By applying the design patterns outlined in this practical book, experienced JavaScript
developers will learn how to write flexible and resilient code that's easier-yes, easier-to work with as your code base
grows.",

"website": "https://chimera.labs.oreilly.com/books/1234000000262/index.html"

},

"isbn": "9781593277574",

"title": "Understanding ECMAScript 6",

"subtitle": "The Definitive Guide for JavaScript Developers",

"author": "Nicholas C. Zakas",

"published": "2016-09-03T00:00:00.000Z",

"publisher": "No Starch Press",

"pages": 352,

"description": "ECMAScript 6 represents the biggest update to the core of JavaScript in the history of the
language. In Understanding ECMAScript 6, expert developer Nicholas C. Zakas provides a complete guide to the
object types, syntax, and other exciting changes that ECMAScript 6 brings to JavaScript.",

"website": "https://leanpub.com/understandinges6/read"

},

"isbn": "9781491904244",

"title": "You Don't Know JS",

"subtitle": "ES6 & Beyond",

"author": "Kyle Simpson",

"published": "2015-12-27T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 278,

"description": "No matter how much experience you have with JavaScript, odds are you don’t fully understand
the language. As part of the 'You Don’t Know JS' series, this compact guide focuses on new features available in
ECMAScript 6 (ES6), the latest version of the standard upon which JavaScript is built.",

"website": "https://github.com/getify/You-Dont-Know-JS/tree/master/es6%20&%20beyond"

Page | 143
},

"isbn": "9781449325862",

"title": "Git Pocket Guide",

"subtitle": "A Working Introduction",

"author": "Richard E. Silverman",

"published": "2013-08-02T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 234,

"description": "This pocket guide is the perfect on-the-job companion to Git, the distributed version control
system. It provides a compact, readable introduction to Git for new users, as well as a reference to common
commands and procedures for those of you with Git experience.",

"website": "https://chimera.labs.oreilly.com/books/1230000000561/index.html"

},

"isbn": "9781449337711",

"title": "Designing Evolvable Web APIs with ASP.NET",

"subtitle": "Harnessing the Power of the Web",

"author": "Glenn Block, et al.",

"published": "2014-04-07T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 538,

"description": "Design and build Web APIs for a broad range of clients—including browsers and mobile devices—
that can adapt to change over time. This practical, hands-on guide takes you through the theory and tools you need
to build evolvable HTTP services with Microsoft’s ASP.NET Web API framework. In the process, you’ll learn how
design and implement a real-world Web API.",

"website": "https://chimera.labs.oreilly.com/books/1234000001708/index.html"

Expressions in JsonPath

Expressions in JsonPath are one of the most powerful features of JsonPath. Note that expressions are also available
in Xpath and CSS Selectors. Expressions help you create a condition that is evaluated to true or false. There are two
important symbols that you have to understand before you can create Expressions in JsonPath.

• ? : Question mark, marks the beginning of an expression. Syntax used [? (Expression)]

• @ : At symbol, signifies the current node being processed. Syntax used $.books[?(@.price > 100)]

Page | 144
Let us now take a simple task from the Json above.

• Find out all the books which have the pages greater than 460

To create a JsonPath which can get us all the books which have pages greater than 460, we have to break the
problem into two parts

1. Create a JsonPath to retrieve all books

2. Append an expression to filter all the books which have pages greater than 460

To get all the books we can create a simple JsonPath: $.books . Now we have to add an expression in the array
books. To do so we will simple start an expression with***?*** sign and then add a filter on the current node @ . A
simple expression will look like this ?(@.pages > 460).

If we combine JsonPath with the expression we will get this: $.books[?(@.pages > 460)]

In the JsonPath Evaluator, simply enter this expression and see the results. As shown in the image below

The result will be all the books with page numbers greater than 460. Here is the result Json

"isbn": "9781593275846",

"title": "Eloquent JavaScript, Second Edition",

"subtitle": "A Modern Introduction to Programming",

"author": "Marijn Haverbeke",

"published": "2014-12-14T00:00:00.000Z",

Page | 145
"publisher": "No Starch Press",

"pages": 472,

"description": "JavaScript lies at the heart of almost every modern web application, from social apps to the newest
browser-based games. Though simple for beginners to pick up and play with, JavaScript is a flexible, complex
language that you can use to build full-scale applications.",

"website": "https://eloquentjavascript.net/"

},

"isbn": "9781449337711",

"title": "Designing Evolvable Web APIs with ASP.NET",

"subtitle": "Harnessing the Power of the Web",

"author": "Glenn Block, et al.",

"published": "2014-04-07T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 538,

"description": "Design and build Web APIs for a broad range of clients—including browsers and mobile devices—
that can adapt to change over time. This practical, hands-on guide takes you through the theory and tools you need
to build evolvable HTTP services with Microsoft’s ASP.NET Web API framework. In the process, you’ll learn how
design and implement a real-world Web API.",

"website": "https://chimera.labs.oreilly.com/books/1234000001708/index.html"

Logical operators in JsonPath

Just like any programming language, JsonPath supports all the logical operators. Below is the list of Logical Operators
that we can use to create expressions. Every logical operator is discussed in detail below.

Operator Description

== left is equal to right (note that 1 is not equal to '1').

!= left is not equal to right.

< left is less than right.

<= left is less or equal to right.

> left is greater than right.

>= left is greater than or equal to right.

Try all the above examples and also try to create more expressions based on your needs. This way you will learn
more about the JsonPath expressions.

Equals to (==) operator in JsonPath

Page | 146
As the name suggests the operator checks if the left-hand side is equal to the right-hand side. Let us find out all the
books that have 352 pages. Here is the JsonPath

JsonPath: $.books[?(@.pages == 352)]

Result will be:

"isbn": "9781593277574",

"title": "Understanding ECMAScript 6",

"subtitle": "The Definitive Guide for JavaScript Developers",

"author": "Nicholas C. Zakas",

"published": "2016-09-03T00:00:00.000Z",

"publisher": "No Starch Press",

"pages": 352,

"description": "ECMAScript 6 represents the biggest update to the core of JavaScript in the history of the language.
In Understanding ECMAScript 6, expert developer Nicholas C. Zakas provides a complete guide to the object types,
syntax, and other exciting changes that ECMAScript 6 brings to JavaScript.",

"website": "https://leanpub.com/understandinges6/read"

Not equal to (!=) operator in JsonPath

When we want to exclude a particular set of values based on a condition we use the not equal to operator. Let us
just invert the example above and find all the books that have page numbers not equal to 352.

JsonPath: $.books[?(@.pages != 352)]

Result will be:

"isbn": "9781593275846",

"title": "Eloquent JavaScript, Second Edition",

"subtitle": "A Modern Introduction to Programming",

"author": "Marijn Haverbeke",

"published": "2014-12-14T00:00:00.000Z",

"publisher": "No Starch Press",

"pages": 472,

"description": "JavaScript lies at the heart of almost every modern web application, from social apps to the newest
browser-based games. Though simple for beginners to pick up and play with, JavaScript is a flexible, complex
language that you can use to build full-scale applications.",
Page | 147
"website": "https://eloquentjavascript.net/"

},

"isbn": "9781449331818",

"title": "Learning JavaScript Design Patterns",

"subtitle": "A JavaScript and jQuery Developer's Guide",

"author": "Addy Osmani",

"published": "2012-07-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 254,

"description": "With Learning JavaScript Design Patterns, you'll learn how to write beautiful, structured, and
maintainable JavaScript by applying classical and modern design patterns to the language. If you want to keep your
code efficient, more manageable, and up-to-date with the latest best practices, this book is for you.",

"website": "https://www.addyosmani.com/resources/essentialjsdesignpatterns/book/"

},

"isbn": "9781449365035",

"title": "Speaking JavaScript",

"subtitle": "An In-Depth Guide for Programmers",

"author": "Axel Rauschmayer",

"published": "2014-02-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 460,

"description": "Like it or not, JavaScript is everywhere these days-from browser to server to mobile-and now you,
too, need to learn the language or dive deeper than you have. This concise book guides you into and through
JavaScript, written by a veteran programmer who once found himself in the same position.",

"website": "https://speakingjs.com/"

},

"isbn": "9781491950296",

"title": "Programming JavaScript Applications",

"subtitle": "Robust Web Architecture with Node, HTML5, and Modern JS Libraries",

"author": "Eric Elliott",

"published": "2014-07-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

Page | 148
"pages": 254,

"description": "Take advantage of JavaScript's power to build robust web-scale or enterprise applications that are
easy to extend and maintain. By applying the design patterns outlined in this practical book, experienced JavaScript
developers will learn how to write flexible and resilient code that's easier-yes, easier-to work with as your code base
grows.",

"website": "https://chimera.labs.oreilly.com/books/1234000000262/index.html"

},

"isbn": "9781491904244",

"title": "You Don't Know JS",

"subtitle": "ES6 & Beyond",

"author": "Kyle Simpson",

"published": "2015-12-27T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 278,

"description": "No matter how much experience you have with JavaScript, odds are you don’t fully understand the
language. As part of the 'You Don’t Know JS' series, this compact guide focuses on new features available in
ECMAScript 6 (ES6), the latest version of the standard upon which JavaScript is built.",

"website": "https://github.com/getify/You-Dont-Know-JS/tree/master/es6+&+beyond"

},

"isbn": "9781449325862",

"title": "Git Pocket Guide",

"subtitle": "A Working Introduction",

"author": "Richard E. Silverman",

"published": "2013-08-02T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 234,

"description": "This pocket guide is the perfect on-the-job companion to Git, the distributed version control
system. It provides a compact, readable introduction to Git for new users, as well as a reference to common
commands and procedures for those of you with Git experience.",

"website": "https://chimera.labs.oreilly.com/books/1230000000561/index.html"

},

"isbn": "9781449337711",

"title": "Designing Evolvable Web APIs with ASP.NET",

Page | 149
"subtitle": "Harnessing the Power of the Web",

"author": "Glenn Block, et al.",

"published": "2014-04-07T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 538,

"description": "Design and build Web APIs for a broad range of clients—including browsers and mobile devices—
that can adapt to change over time. This practical, hands-on guide takes you through the theory and tools you need
to build evolvable HTTP services with Microsoft’s ASP.NET Web API framework. In the process, you’ll learn how
design and implement a real-world Web API.",

"website": "https://chimera.labs.oreilly.com/books/1234000001708/index.html"

Less than ( < ) operator in JsonPath

Less than operator, as the name suggests will return all the values that are less than the value given on the right. Let
us find out all the books with pages less than 352.

JsonPath: $.books[?(@.pages < 352)]

Result will be:

"isbn": "9781449331818",

"title": "Learning JavaScript Design Patterns",

"subtitle": "A JavaScript and jQuery Developer's Guide",

"author": "Addy Osmani",

"published": "2012-07-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 254,

"description": "With Learning JavaScript Design Patterns, you'll learn how to write beautiful, structured, and
maintainable JavaScript by applying classical and modern design patterns to the language. If you want to keep your
code efficient, more manageable, and up-to-date with the latest best practices, this book is for you.",

"website": "https://www.addyosmani.com/resources/essentialjsdesignpatterns/book/"

},

"isbn": "9781491950296",

"title": "Programming JavaScript Applications",

"subtitle": "Robust Web Architecture with Node, HTML5, and Modern JS Libraries",

"author": "Eric Elliott",


Page | 150
"published": "2014-07-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 254,

"description": "Take advantage of JavaScript's power to build robust web-scale or enterprise applications that are
easy to extend and maintain. By applying the design patterns outlined in this practical book, experienced JavaScript
developers will learn how to write flexible and resilient code that's easier-yes, easier-to work with as your code base
grows.",

"website": "https://chimera.labs.oreilly.com/books/1234000000262/index.html"

},

"isbn": "9781491904244",

"title": "You Don't Know JS",

"subtitle": "ES6 & Beyond",

"author": "Kyle Simpson",

"published": "2015-12-27T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 278,

"description": "No matter how much experience you have with JavaScript, odds are you don’t fully understand the
language. As part of the 'You Don’t Know JS' series, this compact guide focuses on new features available in
ECMAScript 6 (ES6), the latest version of the standard upon which JavaScript is built.",

"website": "https://github.com/getify/You-Dont-Know-JS/tree/master/es6+&+beyond"

},

"isbn": "9781449325862",

"title": "Git Pocket Guide",

"subtitle": "A Working Introduction",

"author": "Richard E. Silverman",

"published": "2013-08-02T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 234,

"description": "This pocket guide is the perfect on-the-job companion to Git, the distributed version control
system. It provides a compact, readable introduction to Git for new users, as well as a reference to common
commands and procedures for those of you with Git experience.",

"website": "https://chimera.labs.oreilly.com/books/1230000000561/index.html"

Page | 151
Less than equal to ( <= ) operator in JsonPath

This operator will let you get all the values that are less than or equal to a given value. Let us find out all the books
which have pages less than or equal to 352.

JsonPath: $.books[?(@.pages < 352)]

Result will be:

"isbn": "9781449331818",

"title": "Learning JavaScript Design Patterns",

"subtitle": "A JavaScript and jQuery Developer's Guide",

"author": "Addy Osmani",

"published": "2012-07-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 254,

"description": "With Learning JavaScript Design Patterns, you'll learn how to write beautiful, structured, and
maintainable JavaScript by applying classical and modern design patterns to the language. If you want to keep your
code efficient, more manageable, and up-to-date with the latest best practices, this book is for you.",

"website": "https://www.addyosmani.com/resources/essentialjsdesignpatterns/book/"

},

"isbn": "9781491950296",

"title": "Programming JavaScript Applications",

"subtitle": "Robust Web Architecture with Node, HTML5, and Modern JS Libraries",

"author": "Eric Elliott",

"published": "2014-07-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 254,

"description": "Take advantage of JavaScript's power to build robust web-scale or enterprise applications that are
easy to extend and maintain. By applying the design patterns outlined in this practical book, experienced JavaScript
developers will learn how to write flexible and resilient code that's easier-yes, easier-to work with as your code base
grows.",

"website": "https://chimera.labs.oreilly.com/books/1234000000262/index.html"

},

"isbn": "9781491904244",

"title": "You Don't Know JS",


Page | 152
"subtitle": "ES6 & Beyond",

"author": "Kyle Simpson",

"published": "2015-12-27T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 278,

"description": "No matter how much experience you have with JavaScript, odds are you don’t fully understand the
language. As part of the 'You Don’t Know JS' series, this compact guide focuses on new features available in
ECMAScript 6 (ES6), the latest version of the standard upon which JavaScript is built.",

"website": "https://github.com/getify/You-Dont-Know-JS/tree/master/es6+&+beyond"

},

"isbn": "9781449325862",

"title": "Git Pocket Guide",

"subtitle": "A Working Introduction",

"author": "Richard E. Silverman",

"published": "2013-08-02T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 234,

"description": "This pocket guide is the perfect on-the-job companion to Git, the distributed version control
system. It provides a compact, readable introduction to Git for new users, as well as a reference to common
commands and procedures for those of you with Git experience.",

"website": "https://chimera.labs.oreilly.com/books/1230000000561/index.html"

Greater than ( > ) operator in JsonPath

Greater than operator will let you get all the values which are greater than the value on the left-hand side. Let us
find all the books which have pages more than 460.

JsonPath: $.books[?(@.pages > 460)]

Result will be:

"isbn": "9781593275846",

"title": "Eloquent JavaScript, Second Edition",

"subtitle": "A Modern Introduction to Programming",

"author": "Marijn Haverbeke",

Page | 153
"published": "2014-12-14T00:00:00.000Z",

"publisher": "No Starch Press",

"pages": 472,

"description": "JavaScript lies at the heart of almost every modern web application, from social apps to the newest
browser-based games. Though simple for beginners to pick up and play with, JavaScript is a flexible, complex
language that you can use to build full-scale applications.",

"website": "https://eloquentjavascript.net/"

},

"isbn": "9781449337711",

"title": "Designing Evolvable Web APIs with ASP.NET",

"subtitle": "Harnessing the Power of the Web",

"author": "Glenn Block, et al.",

"published": "2014-04-07T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 538,

"description": "Design and build Web APIs for a broad range of clients—including browsers and mobile devices—
that can adapt to change over time. This practical, hands-on guide takes you through the theory and tools you need
to build evolvable HTTP services with Microsoft’s ASP.NET Web API framework. In the process, you’ll learn how
design and implement a real-world Web API.",

"website": "https://chimera.labs.oreilly.com/books/1234000001708/index.html"

Greater than equal to ( >= ) operator in JsonPath

Greater than equal will let you get all the values that are equal to or greater than value on the right-hand side. Let's
get all the books with pages either greater than or equal to 460

JsonPath: $.books[?(@.pages >= 460)]

Result will be:

"isbn" : "9781593275846",

"title" : "Eloquent JavaScript, Second Edition",

"subtitle" : "A Modern Introduction to Programming",

"author" : "Marijn Haverbeke",

"published" : "2014-12-14T00:00:00.000Z",

"publisher" : "No Starch Press",


Page | 154
"pages" : 472,

"description" : "JavaScript lies at the heart of almost every modern web application, from social apps to the
newest browser-based games. Though simple for beginners to pick up and play with, JavaScript is a flexible, complex
language that you can use to build full-scale applications.",

"website" : "https://eloquentjavascript.net/"

},

"isbn" : "9781449365035",

"title" : "Speaking JavaScript",

"subtitle" : "An In-Depth Guide for Programmers",

"author" : "Axel Rauschmayer",

"published" : "2014-02-01T00:00:00.000Z",

"publisher" : "O'Reilly Media",

"pages" : 460,

"description" : "Like it or not, JavaScript is everywhere these days-from browser to server to mobile-and now you,
too, need to learn the language or dive deeper than you have. This concise book guides you into and through
JavaScript, written by a veteran programmer who once found himself in the same position.",

"website" : "https://speakingjs.com/"

},

"isbn" : "9781449337711",

"title" : "Designing Evolvable Web APIs with ASP.NET",

"subtitle" : "Harnessing the Power of the Web",

"author" : "Glenn Block, et al.",

"published" : "2014-04-07T00:00:00.000Z",

"publisher" : "O'Reilly Media",

"pages" : 538,

"description" : "Design and build Web APIs for a broad range of clients\u2014including browsers and mobile
devices\u2014that can adapt to change over time. This practical, hands-on guide takes you through the theory and
tools you need to build evolvable HTTP services with Microsoft\u2019s ASP.NET Web API framework. In the process,
you\u2019ll learn how design and implement a real-world Web API.",

"website" : "https://chimera.labs.oreilly.com/books/1234000001708/index.html"

Page | 155
Deserialize JSON Array to List
In this tutorial we will talk about the advance usage of JSONPath in Rest Assured which is How to DeSerialize JSON
Array to List. If you have reached here directly, I would suggest that you go through these links before starting with
this.

• REST API Tutorial

• Read JSON Response

• Deserialize JSON Response to Class Object

DeSerialize JSON Array to List

Earlier we saw how JSONPath can be used to make a deterministic and accurate search in the Response JSON. With
this capability, we are able to write better test validations.

In this chapter, we will focus on how we can perform an advance search in the Response JSON by Deserialize JSON
Array to List. We will also learn how we can represent the searched section of Response in various Java data
structures. This tutorial is structured based on different methods available in JSONPath class.

DeSerialize JSON Array to List of String using JSONPath

JsonPath class has two overloaded methods (jsonPath.getList) to extract JSON nodes as a Java List. Here are the
methods

• JsonPath.getList(String) method lets us get the searched nodes as a List of String

• JsonPath.getList(String, Class T) method let us get the searched nodes as a List of T type

To understand we will make a Get call to


the https://bookstore.demoqa.com/swagger/#/BookStore/BookStoreV1BooksGet REST service. This service
returns a JSON response consisting of a collection of books(Array of Books). Each book in the collection is
a JSON object containing values describing the book. You can directly open the URL in the browser to see the output.

To understand JsonPath.getList(String) method we will try to retrieve all the books as a List of
String (List<String>). All we need to do is give "books" as the JSONPath.

Below is the code

@Test

public void JsonPathUsage() throws MalformedURLException

RestAssured.baseURI = "https://restapi.demoqa.com/utilities/books/getallbooks";

Page | 156
RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("");

// First get the JsonPath object instance from the Response interface

JsonPath jsonPathEvaluator = response.jsonPath();

// Read all the books as a List of String. Each item in the list

// represent a book node in the REST service Response

List<String> allBooks = jsonPathEvaluator.getList("books.title");

// Iterate over the list and print individual book item

for(String book : allBooks)

System.out.println("Book: " + book);

Once you run this, the output will be look like this:

Book: Eloquent JavaScript, Second Edition

Book: Learning JavaScript Design Patterns

Book: Speaking JavaScript

Book: Programming JavaScript Applications

Book: Understanding ECMAScript 6

Book: You Don't Know JS

Book: Git Pocket Guide

Book: Designing Evolvable Web APIs with ASP.NET

DeSerialize JSON Array to List of Class (Type T) Object using JSONPath

We all are familiar with Serialization and De-serialization support built-in in Rest-Assured. Let us try to convert the
searched nodes directly into an object representation. In this example let us retrieve all the books from
the JSON response. We will retrieve all the books as a List of Books class. In order to do this, we will first create
a Class Representation of a Book. Get all the properties of JSON Book entity and create a class with those member
variables. A book can be simply represented by a POJO class as shown in the code below.

public class Book {

String isbn;

String title;

Page | 157
String subtitle;

String author;

String published;

String publisher;

int pages;

String description;

String website;

Now to get the response converted into a List of Books we will simply use the JsonPath.getList(String, Class T)
method.

• First parameter is the JSONPath ("books") in this case

• Second parameter is the Type name to which we want the response to be converted. Book class in this case.

Below is the complete code showing the usage

@Test

public void JsonPathUsage() throws MalformedURLException

RestAssured.baseURI = "https://restapi.demoqa.com/utilities/books/getallbooks";

RequestSpecification httpRequest = RestAssured.given();

Response response = httpRequest.get("");

// First get the JsonPath object instance from the Response interface

JsonPath jsonPathEvaluator = response.jsonPath();

// Read all the books as a List of String. Each item in the list

// represent a book node in the REST service Response

List<Book> allBooks = jsonPathEvaluator.getList("books", Book.class);

// Iterate over the list and print individual book item

// Note that every book entry in the list will be complete Json object of book

for(Book book : allBooks)

System.out.println("Book: " + book.title);

Page | 158
}

This is a very good feature of Rest-Assured that enables us to get a targeted part of the response.

Deserialize JSON Array to an Array


Let us learn How to Deserialize JSON Array to an Array? But before we start, it is very important that you go
through the previous set of Tutorials. You can take a look at the tutorials here:

• REST API Automation Testing with Rest-Assured

Deserialize JSON Array to an Array

This tutorial further builds upon our understanding of Deserialization of a JSON Response into an object of a given
Type. Please go through the basics of Serialization and Deserialization in the below tutorial

• Deserialize JSON Data to POJO Class Object

• Deserialize JSON Array to List

We will take an example of demo REST API


endpoint: https://bookstore.demoqa.com/swagger/#/BookStore/BookStoreV1BooksGet If you hit this Endpoint
you will get a Collection of books in the Json response. Below is the response:

"books": [

"isbn": "9781593275846",

"title": "Eloquent JavaScript, Second Edition",

"subtitle": "A Modern Introduction to Programming",

"author": "Marijn Haverbeke",

"published": "2014-12-14T00:00:00.000Z",

"publisher": "No Starch Press",

"pages": 472,

"description": "JavaScript lies at the heart of almost every modern web application, from social apps to the
newest browser-based games. Though simple for beginners to pick up and play with, JavaScript is a flexible, complex
language that you can use to build full-scale applications.",

"website": "https:\/\/fanyv88.com:443\/http\/eloquentjavascript.net\/"

},

"isbn": "9781449331818",

"title": "Learning JavaScript Design Patterns",

"subtitle": "A JavaScript and jQuery Developer's Guide",

"author": "Addy Osmani",

"published": "2012-07-01T00:00:00.000Z",

Page | 159
"publisher": "O'Reilly Media",

"pages": 254,

"description": "With Learning JavaScript Design Patterns, you'll learn how to write beautiful, structured, and
maintainable JavaScript by applying classical and modern design patterns to the language. If you want to keep your
code efficient, more manageable, and up-to-date with the latest best practices, this book is for you.",

"website": "https:\/\/fanyv88.com:443\/http\/www.addyosmani.com\/resources\/essentialjsdesignpatterns\/book\/"

},

"isbn": "9781449365035",

"title": "Speaking JavaScript",

"subtitle": "An In-Depth Guide for Programmers",

"author": "Axel Rauschmayer",

"published": "2014-02-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 460,

"description": "Like it or not, JavaScript is everywhere these days-from browser to server to mobile-and now
you, too, need to learn the language or dive deeper than you have. This concise book guides you into and through
JavaScript, written by a veteran programmer who once found himself in the same position.",

"website": "https:\/\/fanyv88.com:443\/http\/speakingjs.com\/"

},

"isbn": "9781491950296",

"title": "Programming JavaScript Applications",

"subtitle": "Robust Web Architecture with Node, HTML5, and Modern JS Libraries",

"author": "Eric Elliott",

"published": "2014-07-01T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 254,

"description": "Take advantage of JavaScript's power to build robust web-scale or enterprise applications that
are easy to extend and maintain. By applying the design patterns outlined in this practical book, experienced
JavaScript developers will learn how to write flexible and resilient code that's easier-yes, easier-to work with as your
code base grows.",

"website": "https:\/\/fanyv88.com:443\/http\/chimera.labs.oreilly.com\/books\/1234000000262\/index.html"

},

"isbn": "9781593277574",

Page | 160
"title": "Understanding ECMAScript 6",

"subtitle": "The Definitive Guide for JavaScript Developers",

"author": "Nicholas C. Zakas",

"published": "2016-09-03T00:00:00.000Z",

"publisher": "No Starch Press",

"pages": 352,

"description": "ECMAScript 6 represents the biggest update to the core of JavaScript in the history of the
language. In Understanding ECMAScript 6, expert developer Nicholas C. Zakas provides a complete guide to the
object types, syntax, and other exciting changes that ECMAScript 6 brings to JavaScript.",

"website": "https:\/\/fanyv88.com:443\/https\/leanpub.com\/understandinges6\/read"

},

"isbn": "9781491904244",

"title": "You Don't Know JS",

"subtitle": "ES6 & Beyond",

"author": "Kyle Simpson",

"published": "2015-12-27T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 278,

"description": "No matter how much experience you have with JavaScript, odds are you don\u2019t fully
understand the language. As part of the 'You Don\u2019t Know JS' series, this compact guide focuses on new
features available in ECMAScript 6 (ES6), the latest version of the standard upon which JavaScript is built.",

"website": "https:\/\/fanyv88.com:443\/https\/github.com\/getify\/You-Dont-Know-JS\/tree\/master\/es6%20&%20beyond"

},

"isbn": "9781449325862",

"title": "Git Pocket Guide",

"subtitle": "A Working Introduction",

"author": "Richard E. Silverman",

"published": "2013-08-02T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 234,

"description": "This pocket guide is the perfect on-the-job companion to Git, the distributed version control
system. It provides a compact, readable introduction to Git for new users, as well as a reference to common
commands and procedures for those of you with Git experience.",

"website": "https:\/\/fanyv88.com:443\/http\/chimera.labs.oreilly.com\/books\/1230000000561\/index.html"
Page | 161
},

"isbn": "9781449337711",

"title": "Designing Evolvable Web APIs with ASP.NET",

"subtitle": "Harnessing the Power of the Web",

"author": "Glenn Block, et al.",

"published": "2014-04-07T00:00:00.000Z",

"publisher": "O'Reilly Media",

"pages": 538,

"description": "Design and build Web APIs for a broad range of clients\u2014including browsers and mobile
devices\u2014that can adapt to change over time. This practical, hands-on guide takes you through the theory and
tools you need to build evolvable HTTP services with Microsoft\u2019s ASP.NET Web API framework. In the process,
you\u2019ll learn how design and implement a real-world Web API.",

"website": "https:\/\/fanyv88.com:443\/http\/chimera.labs.oreilly.com\/books\/1234000001708\/index.html"

This JSON Response contains an Array of Books. Each item in the JSON Array represents a book and has properties of
a book like "isbn", "title", "author" etc. In the earlier tutorial, we learnt How to Deserialize JSON Resposne of Single
Node to an Instance of Class. However, in Deserializing a Collection of Nodes into Array becomes little tricky. Let us
see how Rest Assured helps us achieve this quickly and without writing any boilerplate code.

Deserialize JSON Array to an Array using JSONPath of Rest Assured?

Similarly, we can convert a Json Array into a Java Array. JsonPath class has method called getObject. This method
can be used to convert the response directly into a Java Array of Book. The only thing the we need to do is
pass Book[].class as the second argument to the method to signify that we want the Json to be deserialized into an
Array of Book. Here is the code that will do this

@Test

public void JsonArrayToArray()

RestAssured.baseURI = "https://restapi.demoqa.com/utilities/books/getallbooks";

RequestSpecification request = RestAssured.given();

Response response = request.get();

System.out.println("Response Body -> " + response.body().asString());

// We can convert the Json Response directly into a Java Array by using
Page | 162
// JsonPath.getObject method. Here we have to specify that we want to

// deserialize the Json into an Array of Book. This can be done by specifying

// Book[].class as the second argument to the getObject method.

Book[] books = response.jsonPath().getObject("books",Book[].class );

for(Book book : books)

System.out.println("Book title " + book.title);

The above two techniques are important to write Concise test code. Apart from writing concise tests by using the
above techniques we fully utilize the features given to us by Rest-Assured. This helps us have lesser dependencies
outside Rest Assured and also enables us to write reliable tests.

What is API Documentation, and Why It Matters?


Automation has a crucial position in this technology-centric world. Faster and short releases are in vogue. In addition
to that, the agile development method has gained a foothold in the software industry. There has been a remarkable
change in the way we develop software automation tests in agile.

Rising Need For API Testing

The old practice of having only the GUI tests for automation does not exist anymore. Moreover, the problems in
software testing with the GUI tests are several. To enumerate a few:

• The tests may fail frequently owing to frequent changes in the UI

• Additional maintenance and refactoring efforts associated with flaky tests

• Moreover, its a time-consuming test process and has slower feedback.

• It requires a large number of initiatives in terms of maintainability and stability.

In a two week aligned sprint, it gets altogether challenging to have a UI ready and test it simultaneously for test
coverage results. Unlike the GUI tests, the API testing doesn't rely on the UI. It becomes much more comfortable to
conjoin/ integrate them under Agile Development. Additionally, it can be brought in much earlier at the
development stage. The increasing/ rising trend of API Testing underlines this further.

An API abstracts the implementation layer, exposing only the objects needed by the developer. It consists
of REST methods. Moreover, these REST methods fetch, manipulate, and delete the data in the application's
database. We need to familiarize ourselves with the workings of REST API basics. Please go through the REST
API tutorials to be acquainted with those.

Once we have familiarised ourselves with the REST API basics, it is time to learn to test the REST APIs. To test a REST
API, we must understand the interface of the API. This includes:

• The operations we can perform using the API

• Structure of the requests

• Structure of responses

Page | 163
Therefore, an essential step in that direction would be to look at the API Documentations. In this article, we are
going to cover:-

• Why do we need an API Documentation?

• What is an API Documentation?

• How to use API Document?

• What are the various types of tests for API?

Let us first understand the benefits of API Documentation.

Why do we need an API Documentation?

Documentation of any technology has a direct impact on the adoption and its usage. Without the knowledge of the
tool, no one would know how to use it. Moreover, there are other advantages to it as listed below:

• It provides a quick and easy guide for API consumption.

• Reduces user frustrations.

• Demonstrates useful functions.

• Saves support costs and time.

These are some of the benefits of API documentation. Let us learn and understand what all consists of an API
Documentation.

What is an API Documentation?

API documents are similar to a reference manual. It talks about the necessary information of an API, in terms of,

Description of Resources

The data returned by the API are resources. Various endpoints can be used to access resources. Under the same
resource, an API will have several routes grouped. Resources and endpoint descriptions are generally short and
precise. Additionally, the user guide contains a piece of more detailed information.

Methods and their endpoints

The endpoint is an essential part of the API documentation. The developers implement it to make the requests.
Endpoints indicate ways to access resources. The methods indicate permissible interactions such as GET, PUT, POST,
or DELETE with the resource. Endpoints, similar to overall resource descriptions, as well have short brief
descriptions. The endpoint shows the end path of a resource. It does not include a common base path to all
endpoints.

Consider a sample APIs collection available to us as TOOLSQA - Bookstore API provided by TOOLSQA. Please
navigate to the URL. Consequently, once the page opens, we will see this:

Page | 164
In the above image:

Bookstore and Account are resources available in Bookstore API

An HTTP method acts as a verb. The listed verbs POST, GET, DELETE in the above image are some of the examples.
Moreover, there are others as well, like PUT, PATCH, OPTION, etc.

The routes in the above image are:

1. /Account/v1/Authorized

2. /Account/v1/GenerateToken

3. /Account/v1/User

4. /Account/v1/User/{GUID}

5. /Account/v1/User/{UserId}

6. /BookStore/v1/Books

7. /BookStore/v1/Books

The routes are following the method to form an endpoint. Example, GET /Account/v1/Authorized.

Note: We have a very few endpoints listed here in the sample bookstore API URL. But in actual projects, the list of
endpoints can be much large.

For an endpoint, the full resource URL needn't be listed in an API document. So, in our example, GET
/Account/v1/Authorized is listed instead of GET http://bookstore.toolsqa.com/Account/v1/Authorized

It is done with the thought to make the users focus on the path. Additionally, the user guide provides the full
resource URL and the needed authorization in the introductory section.

Parameters used

Parameters are the options that control the resource. There are four kinds of parameters:

1. Header parameter: As the name suggests, these are the parameters passed into the request headers. They
are generally related to the authorization and included under a separate section of authorization
Page | 165
requirements for standard header parameters. Additionally, in the case of unique parameters passed in the
headers, they are documented with the respective endpoint.

2. Path parameter: Path parameters are part of the endpoint. They are not optional. We usually write them
along with curly braces. For example, /Account/v1/User/{UserId} Here, {UserId} is the path parameter.

3. Query parameter: They are attached to the URL end. Additionally, the Query Parameter is appended to the
URL after adding '?' at the end of the URL. You can read more in the Query Parameter tutorial.

4. Request body parameters: In a POST request, several times, a JSON object is submitted in the request body.
Moreover, it is a list of key-value pairs.

Example:

"username": "TOOLSQA-Test",

"password": "Test@@123"

Examples of Requests and Responses

Page | 166
In the above example, we passed the username and password as request body parameters. We got a 200 status
code response along with the response body for the POST request of the endpoint /Account/v1/GenerateToken, we
sent.

Alongside, if you notice the highlighted section, it is that of a curl command.

curl -X POST "https://bookstore.toolsqa.com/Account/v1/GenerateToken" -H "accept: application/json" -H


"authorization: Basic VE9PTFNRQS1UZXN0OlRlc3RAQDEyMw==" -H "Content-Type: application/json" -d "{
\"userName\": \"TOOLSQA-Test\", \"password\": \"Test@@123\"}"

We follow Curl format for several reasons:

• Firstly, curl is independent of the programming language.

• Secondly, it consists of the request header information.

• Additionally, it displays the Request method.

Thus, we have understood the contents of a typical API document. An API document may contain additional
information. But the above part of the tutorial gives us a general idea of everything included under an API document.
Subsequently, in our next stage, we will learn the usage of an API document.

How to use an API Document?

To understand the use of Swagger API documentation, we will use the same Bookstore API used previously. It
consists of a sandbox environment that tests the APIs on the documentation.

Navigate to the Bookstore API. You will see the following:

The grouping of endpoints is as follows:

• Account

• BookStore

Some of those API Endpoints listed below build our End to End Rest API Framework. Please try these examples once
you have learned to use the API document at the end of this section.

Page | 167
HTTP VERB Route PURPOSE

POST /Account/v1/GenerateToken To generate token as the endpoint name suggests

GET /Account/v1/User To create a userId with associated user

GET /BookStore/v1/Books To fetch a list of books

POST /BookStore/v1/Books To add a book associated with the user

DELETE /BookStore/v1/Books To remove a book

GET /Account/v1/User/{UserId} To get a list of books associated with userId

We listed some of the APIs below from the bookstore API. They will help us to understand the requests and their
response bodies using Swagger.

1. To Create User

2. To Generate Token with the created User

API Documentation - Create User - POST

Before we begin exploring the APIs, we need to create a user with a username and password. Subsequently, add a
desired username and password under Book Store Credentials.

Note: Please choose your username and password, and once created, remember to use the same username and
password for all the tests. For example, throughout we will be using TOOLSQA-Test as username and Test@@123 as
password.

Now, let's try and create a userID using the POST Request for User.

Make a request

1. First, Expand the POST method for the endpoint under Account: /Account/v1/User

2. Second, click the Try it out button. The Request Body field gets editable.

3. Third, add the username and password. You have added now, as indicated in the below screenshot. After
that, select the parameter content type as application/json. Click on the Execute button.

4. Finally, Swagger submits the request. It shows the curl that was submitted. The Response, for the request, is
observed in the response section.

Page | 168
Note: Please note down the userID. You will need it for other APIs in the request body.

Explanation: We passed a POST Request with username and password in JSON format. We got a 201 status
code along with userID, and books associated with the respective username in the Response body. It explains that
our request was successfully sent over the server, as you can see in the above image under Description. Additionally,
Swagger's implementation is simple and useful. It provides an interactive experience to send a request and receive a
response for APIs.

As software professionals, we need to understand the underpinnings on which great software builds. One of the
many means is to try and test them over in various ways. We familiarized ourselves with the API Documentation.
Additionally, Swagger provided us with the means to test it on Swagger UI itself.

API Documentation - Generate Token - POST

Now that we have created a user in our previous response let's try and create a token using the POST Request for
User.

Page | 169
Explanation: We sent our request with the body containing a username and password in
the application/json format. When we click the Execute button, we got a 200 status code. Additionally, we also got a
response body with the token, expires, status, and result fields. In the next section, we will understand the context
of API tests and study its various types.

What are the various types of API Tests?

Before we commence actual testing of the APIs, we need to compile associated information of the APIs. The context
in which we carry out testing is essential because it drives our testing efforts.

Below is a non-comprehensive list of the information we can seek before we start testing the APIs:

• Expected response code from a successful request

• Expected response code from an unsuccessful request

• Fields to be validated

• Parameters required

• Error handling of unsuccessful requests

• HTTP verbs that we can use with the endpoints

Let us understand, under which all categories the API tests can be divided. It is not to say that we have enlisted a
comprehensive list; there could be more types we can add to the list. But more or less, the API tests fall under one of
the categories mentioned below.

Page | 170
1. Validation Testing: It forms one of the last segments in the software development process. It caters to the
testing explicitly done to assess the product; its behavior, and its efficiency. The API is examined for
correctness in implementation as per the expectations. Additionally, the API is also verified based on pre-
established agreed-upon criteria such as the delivery of specific end goals, integration with the specified
environment. In addition to that, the testing of API's behavior to access the correct data happens as a part of
Validation testing.

2. Functional Testing: This is one of the broader types of testing. It aims to test specified functions. While
testing the APIs for functional testing, the assessment of the responses received happens against expected
responses in terms of passing parameters. Additionally, the error handling for unsuccessful requests and
invalid responses too are under consideration under these tests. The boundary cases, along with regular
tests, fall under the scope of these tests.

3. UI Testing: UI Tests tend to be more specific. These tests assess the user interface against the APIs and their
constituent parts. Additionally, the tests are more generalized with a focus on the API health; it's usability as
well as compatibility of the front end and back end.

4. Load Testing: This test is for the functionality and performance of the APIs under load. The API undergoes
theoretical regular traffic. The test results form the baseline to conduct further load testing. Additionally, the
testing also includes subjecting the API to maximum possible traffic to test the behavior of the API under full
loads. APIs undergo overloading tests. In this test, the verification of the API performance and error handling
conditions during failure happens.

5. Error Detection: The tests for APIs, which include the monitoring, inducing execution errors, sending invalid
requests, detecting operational leaks, etc. fall under this category. The introduction of known failure
scenarios in the APIs happens. The testing of these APIs happens to ensure that the errors are detected,
handled as well as routed.

6. API Security tests: Specific tests verify the APIs performance for vulnerabilities from external threats. Security
testing, Penetration testing, and Fuzz testing are some of them. For example, Security testing involves
validation of the APIs in terms of security requirements. Additionally, these security requirements could be
related to permissions, authorizations, authentications, etc. An authorized attack launches against the
system as a part of Penetration testing. It evaluates the security of the API. A full-scale assessment report of
strengths and weaknesses of the APIs is the deliverable issued after such a test. In Fuzz testing, evaluation of
API behavior happens. It is subjected to unexpected, invalid, and random data of enormous size. Following
this, the crashes, built-in assertions, and memory leaks are known.

7. Integration testing: The Integration tests focus on API communication with another module APIs.

8. Reliability testing: The API should display a prompt response for different configurations. It also looks for a
response data structure as a part of testing.

To conclude, in this post, we have got an understanding of API documentation. We learned to use the Swagger API
document. Additionally, we acquainted ourselves with types of API testing.

In further posts, we will learn to build REST API Automation Framework around the API tests. Try out using the API
document as guided above and reach out for your valuable feedback.

REST API End to End Test


In this tutorial, we will learn to write REST API End to End Test.

We carefully laid the foundations of our API automation framework components. We will be heavily relying on our
previous knowledge gained for Rest Assured, Cucumber as well as Maven. Subsequently, these will form the base
over which we will build our API Automation Framework. I will be referring to them every once in a while and adding
useful links as we need more of them. It's advisable to clear up the basics by going through the tutorials:

Page | 171
1. Rest Assured

2. Cucumber

3. Maven

In our automation framework, we will automate an End to End business flow of a use case. Additionally, it will help
to demonstrate the right examples of framework components and explain their usages. Besides, our understanding
of building the Rest Assured API Automation Framework from scratch will improve as we go about this tutorial.

Many-a-times we are involved in getting ready-made frameworks that are built by Senior Test Architects or Software
Developers. Understanding the underlying principles and design ideas are crucial to develop our skills as software
engineers.

Prerequisites for REST API End to End Test

1. Java Setup

2. IDE Setup

3. Maven Setup

4. Create a maven project

5. Add Rest Assured Dependencies

6. Setup Maven Compiler Plugin

7. Create a user for the test

Step 1 - Java Setup

We will use Java as our language, for writing our REST API automation framework based on the Rest Assured library.
For this, we will need to install Java on our machines if not previously installed. Likewise, please follow through the
tutorial to install Java as our first prerequisite.

Step 2 - IDE Setup

As we will be working with Java, we will need an editor to use for Java. Eclipse, IntelliJ, Net Beans, and several others
are popular IDEs you can choose to work. Furthermore, a tutorial on installing Eclipse on Windows and for Mac users
exists to ease the process. Please pick an IDE you are comfortable working with and get going.

Step 3 - Maven Setup

Build tools enable us to create executable applications from the source code. They help to automate and script
everyday activities like downloading dependencies, compiling, running our tests, and deployments. Moreover, we
will use the Maven build tool for our End To End Scenarios. We have created a tutorial explaining the installation of
Maven on Windows. Additionally, please install Maven, if not previously installed as we would need it.

Step 4: Create a New Maven Project

Eclipse operates with workspaces, folders, and spaces where you add your projects. Software Teams use different
approaches for workspaces and project structures but try to follow and stick with the default structure.

In addition to this, to create a new maven project, please follow our article Steps to create a New Maven Project.
Just to make sure that you specify below values to Maven Archetype Parameters:

• Group ID: ToolsQA

• Artifact ID: API TestingFramework

Page | 172
Note: You can have any names as Group ID and Artifact ID. However, for the ease of this tutorial, it is better to keep
the same naming conventions across the project. Also, it helps in resolving issues while copying pasting the code.

Step 5 - Add Rest Assured Dependencies

We will add Rest Assured Dependencies to our project through the pom.xml file. To add the required dependencies,
go to Rest Assured Maven Repository. Then, select the latest dependency. Copy-paste it in the project pom.xml file.

<dependency>

<groupId>io.rest-assured</groupId>

<artifactId>rest-assured</artifactId>

<version>4.2.0</version>

<scope>test</scope>

</dependency>

Note: As of Feb'2020, the latest rest-assured version is 4.2.0.

We should add the dependency tag within the dependencies tag, like below.

<dependencies>

<dependency>Project Dependency</dependency>

</dependencies>

Further, we will be using JUnit Dependency. So please add that dependency in the pom.xml.

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.13</version>

<scope>test</scope>

</dependency>

Note: As of Feb'2020, the latest JUnit version is 4.13. Always use the latest Junit version.

Step 6: Setup Maven Compiler Plugin

The Compiler Plugin compiles the sources of the project. Regardless of the JDK you run Maven with, the default
source setting is 1.5, and the default target setting is 1.5. Additionally, to change the defaults, please set the source
and target as described in Setting the –source and –target of the Java Compiler.

Below you can find the maven-compiler-plugin settings:

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.7.0</version>

Page | 173
<configuration>

<source>1.8</source>

<target>1.8</target>

<encoding>UTF-8</encoding>

</configuration>

</plugin>

</plugins>

</build>

The complete POM would turn out to be likewise:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="https://maven.apache.org/POM/4.0.0"

xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>ToolsQA</groupId>

<artifactId>RestAssured_APITests</artifactId>

<version>1.0-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.13</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>io.rest-assured</groupId>

<artifactId>rest-assured</artifactId>

<version>4.2.0</version>

<scope>test</scope>

</dependency>

</dependencies>
Page | 174
<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.7.0</version>

<configuration>

<source>1.8</source>

<target>1.8</target>

<encoding>UTF-8</encoding>

</configuration>

</plugin>

</plugins>

</build>

</project>

Step 7: Create an Authorized user for the test

Finally, before we begin automation of our tests, the last piece is remaining. It is of creating an authorized user. We
need to create a user that will use our End to End automation tests. We have learned to create a user in our previous
tutorial under the POST Request. The POST Request tutorial explains how a POST Request method sends data to the
server.

@Test

public void RegistrationSuccessful() {

RestAssured.baseURI = "https://bookstore.toolsqa.com";

RequestSpecification request = RestAssured.given();

JSONObject requestParams = new JSONObject();

/*I have put a unique username and password as below,

you can enter any as per your liking. */

requestParams.put("UserName", "TOOLSQA-Test");

requestParams.put("Password", "Test@@123");

request.body(requestParams.toJSONString());
Page | 175
Response response = request.post("/Account/v1/User");

Assert.assertEquals(response.getStatusCode(), 201);

// We will need the userID in the response body for our tests, please save it in a local variable

String userID = response.getBody().jsonPath().getString("userID");

Write REST API End to End Test:

Let's consider this scenario:-

Test Scenario: As an existing authorized user, I retrieve a list of books available for me in the library. I will assign a
book to myself and later on return it.

We will divide the test scenario into below steps for simplicity:

1. Test will start from generating Token for Authorization - First, we have the username and password of a
registered user. Using these credentials, we will generate a token. Additionally, we will send this token into the
Requests instead of the username and password. The reason we follow this practice is to have specific resources
allocated in a time-bound manner. This step involves making a POST Request call in Rest Assured by passing
username and password. Kindly follow this POST Request tutorial to learn about how to send a POST Request.

Note: The below-mentioned User won't work, please create your user for practice.

2. Get List of available books in the library - Secondly, it is a GET Request call. It gets us, the list of available books.
Visit the GET Request tutorial to understand the logic of how we make a GET Request call in Rest-Assured.

3. Add a book from the list to the user - The third is a POST Request call. We will send the user and book details in
the Request.

4. Delete the added book from the list of books - Fourth is a DELETE Request call. We will delete the added book
from the list. The DELETE Request tutorial will help you with it.

5. Confirm if the book removal happens successfully - Last but not least, as a verification step, we will verify if the
book has got removed from the user. Therefore, we will send user details in a GET Request call to get details of the
user.

Create a Test Package & a Test Class

1. Firstly create a New Package by right click on the src/test/java package and select New >> Package.
Moreover, give your package a name apiTests and click Finish.

2. Secondly, create a New Class file by right click on the src/test/java package and select New >> Class. Give
your test case the correct name in the resulting dialog and click Finish to create the file. Also, to make sure
to check the public static void main, as we will be running the test from the same primary method. I have
named the class as E2E_Tests, as you can see in the code snippet below.

Write the complete REST API End to End Test

I have written an end to end test encompassing the steps as mentioned above. The example is relatively simple to
follow through. Moreover, it involves the use of GET, POST, and DELETE Requests. It will benefit you if you go
through the Rest Assured Tutorial at this point if you are not following.

package apiTests;
Page | 176
import java.util.List;

import java.util.Map;

import org.junit.Assert;

import io.restassured.RestAssured;

import io.restassured.path.json.JsonPath;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class E2E_Tests {

public static void main(String[] args) {

String userID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";

String userName = "TOOLSQA-Test";

String password = "Test@@123";

String baseUrl = "https://bookstore.toolsqa.com";

RestAssured.baseURI = baseUrl;

RequestSpecification request = RestAssured.given();

//Step - 1

//Test will start from generating Token for Authorization

request.header("Content-Type", "application/json");

Response response = request.body("{ \"userName\":\"" + userName + "\", \"password\":\"" + password + "\"}")

.post("/Account/v1/GenerateToken");

Assert.assertEquals(response.getStatusCode(), 200);

String jsonString = response.asString();

Assert.assertTrue(jsonString.contains("token"));
Page | 177
//This token will be used in later requests

String token = JsonPath.from(jsonString).get("token");

//Step - 2

// Get Books - No Auth is required for this.

response = request.get("/BookStore/v1/Books");

Assert.assertEquals(response.getStatusCode(), 200);

jsonString = response.asString();

List<Map<String, String>> books = JsonPath.from(jsonString).get("books");

Assert.assertTrue(books.size() > 0);

//This bookId will be used in later requests, to add the book with respective isbn

String bookId = books.get(0).get("isbn");

//Step - 3

// Add a book - with Auth

//The token we had saved in the variable before from response in Step 1,

//we will be passing in the headers for each of the succeeding request

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

response = request.body("{ \"userId\": \"" + userID + "\", " +

"\"collectionOfIsbns\": [ { \"isbn\": \"" + bookId + "\" } ]}")

.post("/BookStore/v1/Books");

Assert.assertEquals( 201, response.getStatusCode());

//Step - 4
Page | 178
// Delete a book - with Auth

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

response = request.body("{ \"isbn\": \"" + bookId + "\", \"userId\": \"" + userID + "\"}")

.delete("/BookStore/v1/Book");

Assert.assertEquals(204, response.getStatusCode());

//Step - 5

// Get User

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

response = request.get("/Account/v1/User/" + userID);

Assert.assertEquals(200, response.getStatusCode());

jsonString = response.asString();

List<Map<String, String>> booksOfUser = JsonPath.from(jsonString).get("books");

Assert.assertEquals(0, booksOfUser.size());

Note: We added an import statement for JSONpath, import io.restassured.path.json.JsonPath; It will help us to
traverse through the specific parts of the JSON. You can read more in the JSONPath article.

Run the REST API Test

Next step, we need to execute the test. Right-click in the test body and select Run As >> Java Application. The test
will run, and you'll see the results in the Console. Consequently, the program executes successfully without any
error. Just in case you happen to configure the same on IntelliJ IDE, the effect observed will be "Process finished
with exit code 0". Additionally, it is another sign signifying that there were no errors and our tests executed
successfully.

Note: It is not a UI based test. Moreover, there will not be any visual output to observe the test execution.

Conclusively, in the next tutorial, we will Convert our API tests into Cucumber BDD style. It will further our
understanding of the way Cucumber Tests are structured.

REST API Test in Cucumber


In our previous tutorial, we wrote a simple End to End Rest API Test. The business flow of a use case was converted
into a simple API request and response format of GET, POST, and DELETE Requests. Subsequently, our next step is to
Page | 179
convert the REST API Test in Cucumber. While we are at it, we need to develop an understanding of the Cucumber
BDD Framework. The Cucumber tutorials are relatively simple to understand and would be a great primer before we
deep dive.

And now, we start with our Rest API Test in Cucumber.

REST API Test in Cucumber BDD Style Test

We will use the Cucumber BDD Framework to execute our tests. Additionally, it would require us to Convert our
Rest Assured API Tests to the Cucumber BDD Style Test.

The following steps will help us to achieve this:

1. Add Cucumber Dependencies to the Project

2. Write a test in a Feature File

3. Create a Test Runner

4. Write test code to Step file

5. Run test as JUnit test & Maven Command Line

Step 1: Add Cucumber Dependencies to the Project

Firstly, add the following dependencies to our project to execute our tests in Cucumber:

• cucumber-java

• cucumber-jvm-deps

• cucumber-JUnit

As we are developing the framework in Maven, it would be useful to add the dependencies. Therefore, add the
following dependencies into the project POM XML.

cucumber-java: The location of the dependency details is at the [Maven


Repository]tps://mvnrepository.com/artifact/io.cucumber/cucumber-junit/5.2.0).

<dependency>

<groupId>io.cucumber</groupId>

<artifactId>cucumber-java</artifactId>

<version>5.2.0</version>

</dependency>

Note: As of Feb’2020, the latest cucumber-java version is 5.2.0.

cucumber-jvm-deps: The location of the dependency details is at the [Maven


Repository].(https://mvnrepository.com/artifact/io.cucumber/cucumber-jvm-deps)

<dependency>

<groupId>io.cucumber</groupId>

<artifactId>cucumber-jvm-deps</artifactId>

<version>1.0.6</version>

<scope>provided</scope>

</dependency>
Page | 180
Note: As of Feb’2020, the latest cucumber-jvm-deps version is 1.0.6

cucumber-junit: The location of the dependency details is at the Maven Repository.

<dependency>

<groupId>io.cucumber<</groupId>

<artifactId>cucumber-junit</artifactId>

<version>5.2.0</version>

<scope>test</scope>

</dependency>

Note: As of Feb’2020, the latest cucumber-junit version is 5.2.0

Consequently, the complete pom.xml will look like this:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-


instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-
4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>ToolsQA</groupId>

<artifactId>RestAssured_APITests</artifactId>

<version>1.0-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.13</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>io.rest-assured</groupId>

<artifactId>rest-assured</artifactId>

<version>4.2.0</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>io.cucumber</groupId>

<artifactId>cucumber-java</artifactId>

Page | 181
<version>5.2.0</version>

</dependency>

<dependency>

<groupId>io.cucumber</groupId>

<artifactId>cucumber-jvm-deps</artifactId>

<version>1.0.6</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>io.cucumber</groupId>

<artifactId>cucumber-junit</artifactId>

<version>5.2.0</version>

<scope>test</scope>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.7.0</version>

<configuration>

<source>1.8</source>

<target>1.8</target>

<encoding>UTF-8</encoding>

</configuration>

</plugin>

</plugins>

</build>

</project>

Note: Update the POM by right click on the project root and select Maven >> Update Project. This action will nullify
the dependencies based issues.

Additional note: If you feel comfortable adding the jars in the project library instead of using Maven dependencies,
that's alright as well.

Page | 182
Step 2: Write a test in a Feature File

Secondly, we will highly recommend acquainting yourself with the tutorial on the Feature file. It will help in
understanding the basics of the Cucumber feature file. Consequently, we will begin to convert our test scenario into
the Cucumber Feature file.

In the previous chapter, we broke down the scenario into parts for us to easily convert the scenario into steps. Let's
visit the scenario yet again,

1. The test will start by generating a Token for Authorization

2. Get List of available books in the library

3. Add a book from the list to the user

4. Delete the added book from the list of books

5. Confirm if the book removal is successful

Conversion of above scenario to Cucumber BDD Style Test:

• Background: User generates token for Authorisation

Given I am an authorized user

• Scenario: the Authorized user can Add and Remove a book.

Given A list of books are available

When I add a book to my reading list

Then the book is added

When I remove a book from my reading list

Then the book is removed

Create Feature File

1. First, create a New Package and name it as functionalTests. You can do it by right-clicking on
the src/test/resources and select New >> Package.

Note: It's always recommendable to put all the feature files in the resources folder.

2. Secondly, create a Feature file and name it as End2End_Test.feature by right click on the above created
package and select New >> File.

Add .feature extension to the file.

3. Lastly, add the test steps to the feature file.

Page | 183
Note: As you are aware, the keywords used in the test steps are in different colors. Those are the Gherkin keywords.
Eclipse does not understand these. However, if we install the cucumber Eclipse plugin-in, this will be recognized.
Please follow our tutorial to Install Cucumber Eclipse Plugin.

Step 3: Create a JUnit test runner

Thirdly, we will create a Cucumber Test Runner to execute our tests. Moreover, we will need a Cucumber Test
Runner based on the JUnit Test Runner for our tests. To understand more about Cucumber Test Runner, please
refer JUnit Test Runner for the tutorial.

1. Firstly, Right-click on the src/test/java and select a New Package by using New >> Package. Name it
as runners.

2. After that, Create a New Java Class file and name it as TestRunner by right click on the above-created
package and select New >> Class.

package runners;

@RunWith(Cucumber.class)

@CucumberOptions(

features = "src/test/resources/functionalTests",

public class TestRunner {

Note: Do not select the public static void main while creating the runner class.

Step 4: Write test code to Step file

Fourthly, as we move ahead in our next step to convert the test code to Step file, we need to revise our knowledge
on Cucumber Step Definitions.

1. To reduce our efforts in step creation, we will automatically generate the much required Cucumber Steps for
implementation. Consequently, we will execute the TestRunner class for this. Right-click on

Page | 184
the TestRunner file and select Run As >> JUnit Test. Therefore, you would get the below result in the Eclipse
Console.

2. Create a New Package and title it as stepDefinitions by right click on the src/test/java and select New >>
Package.

3. After that, create a New Java Class and name it is as Steps by right click on the above created package and
select New >> Class.

4. Finally, copy all the steps created by Eclipse to this Steps file and start filling up these steps with Selenium
Code. Select all the code from our Selenium Test file created in the End2End_Test. The Steps test file will
look like this:

package stepDefinitions;

import java.util.List;

import java.util.Map;

Page | 185
import org.junit.Assert;

import io.cucumber.java.en.Given;

import io.cucumber.java.en.Then;

import io.cucumber.java.en.When;

import io.restassured.RestAssured;

import io.restassured.path.json.JsonPath;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class Steps {

private static final String USER_ID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";

private static final String USERNAME = "TOOLSQA-Test";

private static final String PASSWORD = "Test@@123";

private static final String BASE_URL = "https://bookstore.toolsqa.com";

private static String token;

private static Response response;

private static String jsonString;

private static String bookId;

@Given("I am an authorized user")

public void iAmAnAuthorizedUser() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

response = request.body("{ \"userName\":\"" + USERNAME + "\", \"password\":\"" + PASSWORD +


"\"}")

.post("/Account/v1/GenerateToken");

String jsonString = response.asString();

Page | 186
token = JsonPath.from(jsonString).get("token");

@Given("A list of books are available")

public void listOfBooksAreAvailable() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

response = request.get("/BookStore/v1/Books");

jsonString = response.asString();

List<Map<String, String>> books = JsonPath.from(jsonString).get("books");

Assert.assertTrue(books.size() > 0);

bookId = books.get(0).get("isbn");

@When("I add a book to my reading list")

public void addBookInList() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

response = request.body("{ \"userId\": \"" + USER_ID + "\", " +

"\"collectionOfIsbns\": [ { \"isbn\": \"" + bookId + "\" } ]}")

.post("/BookStore/v1/Books");

@Then("The book is added")

public void bookIsAdded() {

Assert.assertEquals(201, response.getStatusCode());

Page | 187
@When("I remove a book from my reading list")

public void removeBookFromList() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

response = request.body("{ \"isbn\": \"" + bookId + "\", \"userId\": \"" + USER_ID + "\"}")

.delete("/BookStore/v1/Book");

@Then("The book is removed")

public void bookIsRemoved() {

Assert.assertEquals(204, response.getStatusCode());

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

response = request.get("/Account/v1/User/" + USER_ID);

Assert.assertEquals(200, response.getStatusCode());

jsonString = response.asString();

List<Map<String, String>> booksOfUser = JsonPath.from(jsonString).get("books");

Assert.assertEquals(0, booksOfUser.size());

Note: As compared to our E2E tests created, we have made the following changes:

• Declared the variables as private static final to not allow changes outside the class.
Page | 188
• We have updated method names and not kept the same as auto-generated ones.

5. The TestRunner file must be able to find the steps files. To achieve that, we need to mention the path of the
package. This path has all of our step definitions in CucumberOptions. Additionally, to know more about the
parameters we can add in the @CucumberOptions, please visit our tutorial Cucumber Options.

package runners;

import io.cucumber.junit.Cucumber;

import io.cucumber.junit.CucumberOptions;

import org.junit.runner.RunWith;

@RunWith(Cucumber.class)

@CucumberOptions(

features = "src/test/resources/functionalTests",

glue = {"stepDefinitions"},

monochrome = true,

strict = true

public class TestRunner {

Note: By default, the Junit/Cucumber finds the test code in the src/test/java folder. Hence, this is why we just need to
specify the package name for the cucumber glue.

Step 5: Run the Cucumber Test

Run as JUnit

Finally, we are all set to run the first Cucumber test. Right -Click on TestRunner class and Click Run As >> JUnit
Test. Cucumber will execute the script the same way it runs in Selenium WebDriver. Consequently, the result will
appear in the left-hand side project explorer window in the JUnit tab.

Run the Tests from Command Prompt

Page | 189
We have a Maven Type project, and thus, we can run our tests from the command prompt as well. A simple
command to run tests is an mvn clean test. Moreover, to use this command, we have to change our directory to the
location of our Cucumber project. In the below screenshot first, I went to my project location, and then I used the
Maven as mentioned above command to run the test.

Consequently, we can see the output of the tests below in the command prompt.

To conclude, by now, we have converted our Rest Assured API tests into Cucumber based tests. Subsequently, we
will see how to implement the Java serialization concept in our Framework and enhance it. Moreover, it would be
useful at this stage to go through the Convert JSON to JAVA Object tutorial as a refresher before advancing on the
next framework tutorial.

Convert JSON Request Body to JAVA Object


So far, we have converted our Rest Assured E2E API tests into Cucumber BDD Style Tests. Subsequently, our next
step would Convert JSON to JAVA Object using Serialization. We have covered Serialization and Deserialization
tutorial in Java. It would be highly appreciated if you revisit the Serialization and Deserialization chapter to
understand well what's going around overall in our next stage of framework development.

Convert JSON to JAVA Object

The request body we send right now is in this format:

request.body("{ \"userName\":\"" + USERNAME + "\", \"password\":\"" + PASSWORD + "\"}")

.post("/Account/v1/GenerateToken");

We are sending the body request in a raw JSON string format. It is cumbersome to maintain and error-prone to send
the request body in this format. Right now, we are dealing with just two parameters. But, there is a possibility that in
actual body requests, we could have to deal with more number of parameters.

Additionally, it is advisable to send the username and password in the request body as an object. To achieve this we
need to convert JSON to JAVA Object. But, the network does not understand Java objects. So, we would need to
serialize the objects into String before sending the request.

We can do this using many serialization-deserialization libraries available. But, Rest Assured has this functionality in-
built. It enables us to directly send objects in Rest Assured requests while the Library takes care of Serialization
internally. If you dive deeper to understand the implementation of RequestSpecification, you will see the below code
snippet which clearly shows how Rest Assured takes care of Serialization.

Page | 190
So we will now understand the process of converting a JSON request into a Java object in the next section.

Create a POJO class for a Request Body

We are focussing on creating a POJO class for our request object. So, let us learn to create a POJO class out of
a JSON. Let's begin with one simple request example from our Request Body:

Consider the API endpoint: /Account/v1/GenerateToken

In the Request body for this API, we are sending the username and password as the request body.

As seen in the above Swagger bookstore API document, the request JSON body parameters we pass in the request
body is:

"userName": "TOOLSQA-Test",
Page | 191
"password": "Test@@123"

Moreover, you can manually create a POJO class having all listed fields of the JSON body. Also, there are various
utilities available online for free using which we can convert any JSON structure to a Java POJO class.

How to create a Java POJO Class for a JSON Request Body using Online Utility?

Here we will see How to Convert a JSON String into Java Object. So, let's take the help of one of the websites to
help us convert the JSON to a Java POJO class.

Please follow these steps

• Firstly, navigate to the website: http://www.jsonschema2pojo.org/

• Secondly, enter the JSON body in the left text box.

• Thirdly, enter the package name and class name in the right-side panel.

• Finally, enter other required selection details as per the image below.

Click on the preview button highlighted in the above image.

The following image is displayed:

Page | 192
Explanation

Thus, with our inputs of a JSON with username and password as fields, we have created a POJO. Additionally, we will
use this POJO to send into the request body of our API /Account/v1/GenerateToken.

Steps to Update the JSON String with POJO classes

We will follow these steps to implement serialization in our framework:

1. Firstly, create POJO classes for each of our Request Objects:

• Token Request

• Add Books Request

• ISBN

• Remove Books Request

2. Secondly, replace the Request bodies in Step files with POJO class objects.

3. Finally, run the tests.

POJO class for Authorization Token Request:

Page | 193
As shown in the above image from our Swagger bookstore API documentation for the Generate Token API, the
request body is:

"userName": "TOOLSQA-Test",

"password": "Test@@123"

To create a POJO class of it, please follow the below steps:

1. Firstly, Right-click on the src/test/java and select New >> Package. After that, create a New Package file and
name it as apiEngine. Further inside, the apiEngine Package creates a new Package with the name as
the model. Moreover, inside this model Package, create a Package with the name requests. We will capture
all the requests classes under this package.

2. Secondly, create a New Class file under it and name it as AuthorizationRequest, by right click on the above-
created Package and select New >> Class.

AuthorizationRequest.class

package apiEngine.model.requests;

public class AuthorizationRequest {

public String username;

public String password;

public AuthorizationRequest(String username, String password) {

this.username = username;

this.password = password;

Code Explanation

The Bookstore URL requires the client to send the username and password as we studied in the API Documentation
tutorial for Authorization Token. We have defined the class AuthorizationRequest for this purpose. We will create an
object of AuthorizationRequest with a constructor with the parameters username and password.

Similarly, we will create classes for Add Books Request, Remove Books Request, and ISBN.

POJO class for Add Books Request:

As we saw in the Swagger bookstore API documentation for the Add Books API, the request body is:

"userId": "string",

"collectionOfIsbns": [

Page | 194
{

"isbn": "string"

To create a POJO class of the JSON request body, Right-click on the above-created request Package and select New
>> Class. Additionally, name it as AddBooksRequest.

AddBooksRequest.class

package apiEngine.model.requests;

import java.util.ArrayList;

import java.util.List;

public class AddBooksRequest {

public String userId;

public List<ISBN> collectionOfIsbns;

//As of now this is for adding a single book, later we will add another constructor.

//That will take a collection of ISBN to add multiple books

public AddBooksRequest(String userId, ISBN isbn){

this.userId = userId;

collectionOfIsbns = new ArrayList<ISBN>();

collectionOfIsbns.add(isbn);

Code Explanation

The AddBooksRequest class will be responsible for providing us an object that adds a book into the user account.
While we are at it, we would need the userId and the unique identifier of the book, ISBN. Thus,
the userID and isbn pass as a parameter into the AddBooksRequest class object.

POJO class for ISBN:

Right-click on the above-created request Package. After that, select New >> Class. Name it as ISBN.

package apiEngine.model.requests;

Page | 195
public class ISBN {

public String isbn;

public ISBN(String isbn) {

this.isbn = isbn;

Code Explanation

We created the ISBN class to use in the AddBooksRequest class for storing a collection of the type ISBN.

POJO class for Remove Book Request:

As we saw in the Bookstore API for Remove Books Endpoint, the request body is:

"isbn": "string",

"userId": "string"

To create a POJO class of the JSON request body, Right-click on the above-created request Package and select New
>> Class. Additionally, name it as RemoveBookRequest.

package apiEngine.model.requests;

public class RemoveBookRequest {

public String isbn;

public String userId;

public RemoveBookRequest(String userId, String isbn) {

this.userId = userId;

this.isbn = isbn;

Code Explanation

With the help of RemoveBooksRequest class, we will create an object by passing the parameters userId and isbn.
Moreover, the request body uses this object.

Replace the Request Bodies in Step files with POJO class objects

Lets just first start with the first step of the test that is "Given("^I am an authorized user$")"

We made the following change in its Step Definition:

Page | 196
@Given("^I am an authorized user$")

public void iAmAnAuthorizedUser() {

AuthorizationRequest authRequest = new AuthorizationRequest("TOOLSQA-Test","Test@@123");

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

response = request.body(authRequest).post("/Account/v1/GenerateToken");

String jsonString = response.asString();

token = JsonPath.from(jsonString).get("token");

Code Explanation

We have created an object, authRequest of the class AuthorizationRequest. In this object, we are
passing username and password. Additionally, this authRequest object will pass in the body of the request.

In a similar vein, we will make changes for the following Step Definitions to use Java objects that we created using
the POJOs we defined. Internally, the rest assured library will take care of serializing this object into JSON string
before sending the request over the network. Thus, we do not have to worry about serializing the request objects.

@When("^I add a book to my reading list$")

@When("I remove a book from my reading list")

Also, note that for the remaining three Step Definitions, we would not be making any changes for now.

@Given("A list of books are available")

@Then("^The book is added$")

@Then("^The book is removed$")

We put together all these code changes for Steps file

package stepDefinitions;

import java.util.List;

import java.util.Map;

import apiEngine.model.requests.AddBooksRequest;

import apiEngine.model.requests.AuthorizationRequest;

import apiEngine.model.requests.ISBN;

import apiEngine.model.requests.RemoveBookRequest;
Page | 197
import org.junit.Assert;

import cucumber.api.java.en.Given;

import cucumber.api.java.en.Then;

import cucumber.api.java.en.When;

import io.restassured.RestAssured;

import io.restassured.path.json.JsonPath;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class Steps {

private static final String USER_ID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";

private static final String BASE_URL = "https://bookstore.toolsqa.com";

private static String token;

private static Response response;

private static String jsonString;

private static String bookId;

@Given("^I am an authorized user$")

public void iAmAnAuthorizedUser() {

AuthorizationRequest credentials = new AuthorizationRequest("TOOLSQA-Test","Test@@123");

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

response = request.body(credentials).post("/Account/v1/GenerateToken");

String jsonString = response.asString();

token = JsonPath.from(jsonString).get("token");

Page | 198
@Given("^A list of books are available$")

public void listOfBooksAreAvailable() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

response = request.get("/BookStore/v1/Books");

jsonString = response.asString();

List<Map<String, String>> books = JsonPath.from(jsonString).get("books");

bookId = books.get(0).get("isbn");

@When("^I add a book to my reading list$")

public void addBookInList() {

AddBooksRequest addBooksRequest = new AddBooksRequest(USER_ID, new ISBN(bookId));

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

response = request.body(addBooksRequest).post("/BookStore/v1/Books");

@Then("^The book is added$")

public void bookIsAdded() {

Assert.assertEquals(201, response.getStatusCode());

@When("^I remove a book from my reading list$")

public void removeBookFromList() {

RestAssured.baseURI = BASE_URL;
Page | 199
RequestSpecification request = RestAssured.given();

RemoveBookRequest removeBookRequest = new RemoveBookRequest(USER_ID, bookId);

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

response = request.body(removeBookRequest).delete("/BookStore/v1/Book");

@Then("^The book is removed$")

public void bookIsRemoved(){

Assert.assertEquals(204, response.getStatusCode());

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

response = request.get("/Account/v1/User/" + USER_ID);

Assert.assertEquals(200, response.getStatusCode());

jsonString = response.asString();

List<Map<String, String>> booksOfUser = JsonPath.from(jsonString).get("books");

Assert.assertEquals(0, booksOfUser.size());

Note: We added an import statement for JSONpath, import io.restassured.path.json.JsonPath; It will help us to
traverse through the specific parts of the JSON. Moreover, you can read more in the JSONPath article.

Now, if we try to run our tests, using TestRunner after making all the changes in the Steps file, our tests will fail.

The Runtime-Exception, we will come across is:

java.lang.IllegalStateException: Cannot serialize object because no JSON serializer found in classpath. Please put
Jackson (Databind), Gson, Johnzon, or Yasson in the classpath.

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

Page | 200
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)

at java.lang.reflect.Constructor.newInstance(Unknown Source)

at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:80)

at
org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(Construc
torSite.java:105)

at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)

at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:237)

at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:249)

at io.restassured.internal.mapping.ObjectMapping.serialize(ObjectMapping.groovy:160)

at io.restassured.internal.mapping.ObjectMapping$serialize.call(Unknown Source)

at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)

at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)

at io.restassured.internal.RequestSpecificationImpl.body(RequestSpecificationImpl.groovy:751)

at stepDefinitions.Steps.iAmAnAuthorizedUser(Steps.java:38

We are missing a key element in the whole show. As explained above in the first section, Rest Assured takes care of
Serialization internally. We also confirmed it in the code snippet. The Rest Assured library depends on the Jackson
(Databind) library, to do this work of Serialization. Since we haven’t yet added this library, we faced the error.

Let us quickly add the dependency in our framework project file pom.xml:

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>

<version>2.10.2</version>

</dependency>

Note: As of Feb 2019, the latest available dependency for jackson-databind was of version 2.10.2. Please use the
latest dependencies when you build your framework.

Our new POM file will look like this:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-


instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-
4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>ToolsQA</groupId>

<artifactId>APITestingFramework</artifactId>

Page | 201
<version>1.0-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.13</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>io.rest-assured</groupId>

<artifactId>rest-assured</artifactId>

<version>4.2.0</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>io.cucumber</groupId>

<artifactId>cucumber-java</artifactId>

<version>5.2.0</version>

</dependency>

<dependency>

<groupId>io.cucumber</groupId>

<artifactId>cucumber-jvm-deps</artifactId>

<version>1.0.6</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>io.cucumber</groupId>

<artifactId>cucumber-junit</artifactId>

<version>5.2.0</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>
Page | 202
<version>2.10.2</version>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.7.0</version>

<configuration>

<source>1.8</source>

<target>1.8</target>

<encoding>UTF-8</encoding>

</configuration>

</plugin>

</plugins>

</build>

</project>

Run the Cucumber Test

Run the Tests as JUnit

Now we are all set to run the updated Cucumber test. Right -Click on TestRunner class, and after that, click Run
As >> JUnit Test. Consequently, the result will display in the JUnit tab of the console.

Run the Tests from Cucumber Feature

To run the tests as a Cucumber Feature, right-click on the End2End_Test.feature file. After that, select the Run
As>>Cucumber Feature.

Page | 203
As you can see in the screenshot attached above, our tests have passed with the changes. We have Convert JSON to
JAVA Object using Serialization in this chapter. Please try to implement it in your framework, as explained above.
Below is the screenshot of the current project explorer.

Page | 204
Subsequently, we will visit the Convert JSON Response Body to POJO in our next chapter.

Convert JSON Response Body to Java Object


In this chapter, we will implement the Deserialization of JSON Responses we receive. It helps us to read the body of
the response. Subsequently, in this process of deserialization, we will Convert JSON Response Body to Java Objects.
It is also known as Object Representation of JSON responses.

Additionally, to learn more about the deserialization of JSON response, we will recommend you to go through
the Deserialize JSON Response.

We will follow the below steps to achieve the deserialization of our responses in the framework. We followed them
in the previous chapter of Convert JSON Request Body to Java Object as well.

1. Create POJO classes for each of our Response Objects:

• Book

Page | 205
• Books

• Token

• User Account

2. Replace the Response bodies in Step files with POJO class objects

3. Run the tests

Convert JSON Response Body to Java Object

Firstly, we need to convert the JSON Response into a POJO class for our response object. So, let us learn to create
a POJO class out of a JSON Response. Under deserialization, we will study our JSON body parameters and create
a POJO class of it. Let's begin with a straightforward request example for Get A Book request:

Create POJO class Book

As a part of this request, we are sending the ISBN parameter to get details of a specific book.

Consequently, the response body from the Swagger Bookstore API, as highlighted in the above image is:

Page | 206
{

"books": [

"isbn": "9781449325862",

"title": "Git Pocket Guide",

"subTitle": "A Working Introduction",

"author": "Richard E. Silverman",

"published": "2013-08-02T00:00:00",

"publisher": "O'Reilly Media",

"pages": 234,

"description": "This pocket guide is the perfect on-the-job companion to Git, the distributed version control
system. It provides a compact, readable introduction to Git for new users, as well as a reference to common
commands and procedures for those of you with Git experience.",

"website": "https://chimera.labs.oreilly.com/books/1230000000561/index.html"

As a part of the next step, we will create a POJO class for our response object. Additionally, you may use the
same online utility, as we discussed in the previous chapter, to convert the response to a POJO class.

To create a POJO class of it, follow the below steps:

1. Firstly, Right-click on the model Package under the apiEngine package. After that, select New>>Class. Name it as
Book. Moreover, we will capture the book response under this class.

Book.class

package apiEngine.model;

public class Book {

public String isbn;

public String title;

public String subTitle;

public String author;

public String published;

public String publisher;

public int pages;

public String description;

public String website;

Page | 207
Code Explanation

This Book class will contain all the fields we got in the response, such as title, isbn, author, no.of pages, etc.

Create a POJO class for Books Response Object:

The response body from the Bookstore API, as highlighted in the below image is:

"userID": "9b5f49ab-eea9-45f4-9d66-bcf56a531b85",

"userName": "TOOLSQA-Test",

"books": [

"isbn": "9781449325862",

Page | 208
"title": "Git Pocket Guide",

"subTitle": "A Working Introduction",

"author": "Richard E. Silverman",

"published": "2013-08-02T00:00:00",

"publisher": "O'Reilly Media",

"pages": 234,

"description": "This pocket guide is the perfect on-the-job companion to Git, the distributed version control
system. It provides a compact, readable introduction to Git for new users, as well as a reference to common
commands and procedures for those of you with Git experience.",

"website": "https://chimera.labs.oreilly.com/books/1230000000561/index.html"

Note: As a part of the response body, we got the book details of the book we added for the user as well as other user
details such as userName and userID.

To create a POJO class of it, follow the below steps:

1. Firstly, in this model Package, Right-click on the model and select New >> Package. Name it
as responses. Additionally, we will capture all the response classes under this package.

2. Secondly, Right-click on the above-created responses Package and select New >> Class. Name it as Books.

Books.class

package apiEngine.model.responses;

import java.util.List;

import apiEngine.model.Book;

public class Books {

public List<Book> books;

Code Explanation We created the class Books to hold a list of the type Book which we receive in the JSON response
in GET Books Request.

Create a POJO class for Token Object:

We have understood the process of creating a POJO class by now, as shown in the above examples. So, in the next
APIs, I will directly add the POJO of respective API's. Consequently, the response body for Generate Token API from
our Bookstore API is:

"token": "string",

Page | 209
"expires": "2020-03-14T13:42:15.716Z",

"status": "string",

"result": "string"

To create a POJO class of it, Right-click on the above-created responses Package and select New >> Class. After that,
name it as Token.

package apiEngine.model.responses;

public class Token {

public String token;

public String expires;

public String status;

public String result;

Code Explanation

We created the class Token that will contain all the fields we got in the response field, namely, token, expiry, status,
and a result which we receive in the JSON response of GenerateToken.

Create a POJO class for User Account Object:

Similarly, for User Account API, the response body is:

"userID": "9b5f49ab-eea9-45f4-9d66-bcf56a531b85",

"userName": "TOOLSQA-Test",

"books": []

To create a POJO class of the response body, Right-click on the above-created responses Package. After that,
select New >> Class. Name it as UserAccount.

package apiEngine.model.responses;

import java.util.List;

import apiEngine.model.Book;

public class UserAccount {

public String userID;

public String userName;

public List<Book> books;


Page | 210
}

Code Explanation

We created the class UserAccount to hold the information associated with the user account, such as books
associated with the user, the userID, and userName.

As our next step of project implementation, we shall modify our Steps class.

Replace the Response bodies in Step files with POJO class objects

Now it is the time to make use of the POJO classes created above in the test code. Let's have a look at the one of the
old cucumber step below in the Step Definition:

@Given("^I am an authorized user$")

public void iAmAnAuthorizedUser() {

AuthorizationRequest credentials = new AuthorizationRequest("TOOLSQA-Test","Test@@123");

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

response = request.body(credentials).post("/Account/v1/GenerateToken");

String jsonString = response.asString();

//We will deserialize the Response body into Token Response

token = JsonPath.from(jsonString).get("token");

we update it likewise:

@Given("^I am an authorized user$")

public void iAmAnAuthorizedUser() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

AuthorizationRequest authRequest = new AuthorizationRequest("TOOLSQA-Test", "Test@@123");

response = request.body(authRequest).post("/Account/v1/GenerateToken");

Page | 211
// Deserializing the Response body into tokenResponse

tokenResponse = response.getBody().as(Token.class);

Note The import statement: import io.restassured.path.json.JsonPath; is no longer needed as we have deserialized
our response to Token class.

Code Explanation: We deserialized the response body into the Token class in this step above. This response body
gets saved in the "tokenResponse" variable. The saved variable will be used further in a request along with the
token.

We put together these code snippets for our Steps file:

package stepDefinitions;

import java.util.List;

import java.util.Map;

import org.junit.Assert;

import apiEngine.model.Book;

import apiEngine.model.requests.AddBooksRequest;

import apiEngine.model.requests.AuthorizationRequest;

import apiEngine.model.requests.ISBN;

import apiEngine.model.requests.RemoveBookRequest;

import apiEngine.model.response.Books;

import apiEngine.model.response.Token;

import apiEngine.model.response.UserAccount;

import io.cucumber.java.en.Given;

import io.cucumber.java.en.Then;

import io.cucumber.java.en.When;

import io.restassured.RestAssured;

import io.restassured.path.json.JsonPath;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class Steps {

private static final String USER_ID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";


Page | 212
private static final String BASE_URL = "https://bookstore.toolsqa.com";

private static Response response;

private static Token tokenResponse;

private static Book book;

@Given("I am an authorized user")

public void iAmAnAuthorizedUser() {

AuthorizationRequest credentials = new AuthorizationRequest("TOOLSQA-Test","Test@@123");

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

response = request.body(credentials).post("/Account/v1/GenerateToken");

// Deserializing the Response body into tokenResponse

tokenResponse = response.getBody().as(Token.class);

@Given("A list of books are available")

public void listOfBooksAreAvailable() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

response = request.get("/BookStore/v1/Books");

// Deserializing the Response body into Books class

Books books = response.getBody().as(Books.class);

book = books.books.get(0);

@When("I add a book to my reading list")


Page | 213
public void addBookInList() {

ISBN isbn = new ISBN(book.isbn);

AddBooksRequest addBooksRequest = new AddBooksRequest(USER_ID, isbn);

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + tokenResponse.token)

.header("Content-Type", "application/json");

response = request.body(addBooksRequest).post("/BookStore/v1/Books");

@Then("The book is added")

public void bookIsAdded() {

Assert.assertEquals(201, response.getStatusCode());

UserAccount userAccount = response.getBody().as(UserAccount.class);

Assert.assertEquals(USER_ID, userAccount.userID);

Assert.assertEquals(book.isbn, userAccount.books.get(0).isbn);

@When("I remove a book from my reading list")

public void removeBookFromList() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

RemoveBookRequest removeBookRequest = new RemoveBookRequest(USER_ID, book.isbn);

request.header("Authorization", "Bearer " + tokenResponse.token)

.header("Content-Type", "application/json");

response = request.body(removeBookRequest).delete("/BookStore/v1/Book");

}
Page | 214
@Then("The book is removed")

public void bookIsRemoved() {

Assert.assertEquals(204, response.getStatusCode());

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + tokenResponse.token)

.header("Content-Type", "application/json");

response = request.get("/Account/v1/User/" + USER_ID);

Assert.assertEquals(200, response.getStatusCode());

UserAccount userAccount = response.getBody().as(UserAccount.class);

Assert.assertEquals(0, userAccount.books.size());

Run the Cucumber Test

Run the Tests as JUnit

We are all set now to run the updated Cucumber test. First, Right -Click on TestRunner class and Click Run
As >> JUnit Test. Cucumber runs the script in the same way as Selenium WebDriver. Consequently, the result will
display in the JUnit tab of the console.

Run the Tests from Cucumber Feature

To run the tests as a Cucumber Feature, right-click on the End2End_Test.feature file. After that, select the Run
As>>Cucumber Feature.

Page | 215
Our tests passed with the changes we made for the conversion of the JSON Response Body to Java Object. Please try
to implement it in your framework, as explained above, and share your valuable feedback.

After creating the above POJO classes, the project folder structure will look likewise:

Subsequently, we will attempt the separation of Test Layer with API Services in our next chapter.

Page | 216
Separation of Test Layer with API Services
We learned to convert JSON Request Body as well as JSON Response Body to Java Object in the previous chapters.
We used Serialization and Deserialization concepts to achieve this. It led to our tests becoming more maintainable
and less error-prone. Now in this chapter, we will work on the Separation of Test Layer with API Services and take a
step further to make our tests cleaner and maintainable.

If you look at the Steps class, which is our test layer, you would see that we have a lot of logic that isn't actually
related to testing. It concerns communicating with the server with a given test request and getting a response. Refer
to the screenshot below:

In actual projects, we have a large number of APIs and tests implemented. They all contain the same logic of
communicating with the server in every test, like:

• Buiding RequestSpecification object

• Adding headers

• Making calls to the server

This leads to a lot of code duplication in every test file. Additionally, if tomorrow there are some changes required in
a particular endpoint, we will need to make changes in several places. It is not advisable because it makes our
framework less maintainable.

Additionally, the test layer needs to focus only on the test data (parameters) sent in the request and receive
responses from the APIs. It should not be focused on the heavy logic of the internals of API implemented. So, as
software testers, we are only interested in the request and response obtained for these requests. Moreover, the test
data sent in the request generally pass from the feature file in the Cucumber framework. This test data can be
parameters to form a request body, request header or request resources.

As we have seen in our first chapter Understanding API Documentation, endpoints indicate ways to access
resources from the server. Thus, we will essentially combine all the logic of endpoints from our Steps file and move it
to a common class. The class will contain methods that take the required request parameters and send back a
Page | 217
response received from the server. The endpoints should always get the request body from the test layer. In this
article, we are going to cover:-

• Separation of Test Layer with API Services

• Create API Services for the Test

o Create API Services

o Add methods of API Services

o Call API Services in the Step Definitions(test layer)

o Run the tests

Separation of Test Layer with API Services

We abstract the logic of communication with the server into a separate class. It will make our Steps class cleaner.
Subsequently, as we progress to write more steps into Step-Definition files in the framework, for different scenarios,
we can reuse this logic of communicating with the server.

Consider the example to generate a token request of our Book Store API: /Account/v1/GenerateToken

For writing tests to test the generate token, our tests should focus the response obtained for the request body
passed. In addition to this, they should not focus on internal implementation for the API. In a project with a large
number of APIs, it is better to separate the Endpoints from Steps file.

Moreover, if we send correct credentials, we get a success response as a result. Refer below screenshot:

Page | 218
But, if we send invalid credentials, we will get an error response.

Thus, as testers, the focus is on the parameters sent in the body of the request and response we get. It is as same as
what we are doing at the Book Store API in Swagger Tool above. We do not have a clue how swagger is making use
of HTTP and how it is communicating with the server. The same way the test layer should be agnostic, the fact of
how the service layer is handling the request. Additionally, a test layer should only focus on parameters passed to
the request, whether it is query parameter, header parameters, or a body parameter, etc.

Let's see how to separate the Service layer from the Test layer.

Create API Services for the Test

Now we are going to create API Services, which will be consumed by the test layer, and this way, the test layer will
be clean and efficiently focus only on test parameters.

1. Firstly, create API Services

2. Secondly, add methods of API Services

3. Thirdly, call API Services in the Step Definitions(test layer)

4. Fourthly, run the tests

Create API Services


Page | 219
1. Firstly, Right-click on the apiEngine package and select Class. Additionally, name it as Endpoints. It would be
our API Services class.

package apiEngine;

public class Endpoints {

We are moving all our endpoints to the Endpoints class. It is rational to move the BASE URL as well to the Endpoints
class from Steps file. Moreover, it will help us to refer to the BASE URL when sending requests to our endpoints.

Thus, the updated Endpoints class will look likewise:

package apiEngine;

public class Endpoints {

private static final String BASE_URL = "https://bookstore.toolsqa.com";

Add methods of API Services

Firstly, we will extract the way to authenticate the user from Steps into Endpoints class. Additionally, we shall pass
the object of *AuthorizationRequest *to the method.

public static Response authenticateUser(AuthorizationRequest authRequest) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.body(authRequest).post("/Account/v1/GenerateToken");

return response;

Code Explanation:

As you can see, we have created a method authenticateUser. In this method, we pass user credentials
through AuthorizationRequest object, authRequest in the Request. Moreover, we are passing the BASE_URL and the
headers as part of the request as well.

Similar to the above authenticateUser() method, we will create methods for :

• getBooks()

• addBook()

• removeBook()

• getUserAccount()

Putting all the methods together for the Endpoints class:

Endpoints.java class

package apiEngine;

Page | 220
import apiEngine.model.requests.AddBooksRequest;

import apiEngine.model.requests.AuthorizationRequest;

import apiEngine.model.requests.RemoveBookRequest;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class EndPoints {

private static final String BASE_URL = "https://bookstore.toolsqa.com";

public static Response authenticateUser(AuthorizationRequest authRequest) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.body(authRequest).post("/Account/v1/GenerateToken");

return response;

public static Response getBooks() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.get("/BookStore/v1/Books");

return response;

public static Response addBook(AddBooksRequest addBooksRequest, String token) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)


Page | 221
.header("Content-Type", "application/json");

Response response = request.body(addBooksRequest).post("/BookStore/v1/Books");

return response;

public static Response removeBook(RemoveBookRequest removeBookRequest, String token) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

Response response = request.body(removeBookRequest).delete("/BookStore/v1/Book");

return response;

public static Response getUserAccount(String userId, String token) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

Response response = request.get("/Account/v1/User/" + userId);

return response;

We now move to our next step. In the next step, we will replace the endpoints in the Steps file with our newly
created methods.

Talk with API Services in the Step Definitions

Page | 222
We have abstracted the logic of communication with the server into an Endpoint class. It will now help us make our
Steps class cleaner as we progress into replacing the endpoints with the associated methods. In addition to this, we
will be reusing this logic of communicating with the server.

Thus, the first part of the Steps class, with changes in the declared variables will be:

public class Steps {

private static final String USER_ID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";

private static Response response;

private static Token tokenResponse;

private static Book book;

For the step definition:

@Given("I am an authorized user")

is updated as:

@Given("I am an authorized user")

public void iAmAnAuthorizedUser() {

AuthorizationRequest authRequest = new AuthorizationRequest("TOOLSQA-Test", "Test@@123");

response = EndPoints.authenticateUser(authRequest);

tokenResponse = response.getBody().as(Token.class);

We will likewise modify the rest of our step definitions. Moreover, we put all these changes for the Step Definitions
together into the Steps file.

The updated Steps file will look likewise:

package stepDefinitions;

import java.util.List;

import java.util.Map;

import org.junit.Assert;

import apiEngine.Endpoints;

import apiEngine.model.Book;

import apiEngine.model.requests.AddBooksRequest;

import apiEngine.model.requests.AuthorizationRequest;

import apiEngine.model.requests.ISBN;

import apiEngine.model.requests.RemoveBookRequest;
Page | 223
import apiEngine.model.response.Books;

import apiEngine.model.response.Token;

import apiEngine.model.response.UserAccount;

import io.cucumber.java.en.Given;

import io.cucumber.java.en.Then;

import io.cucumber.java.en.When;

import io.restassured.response.Response;

public class Steps {

private static final String USER_ID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";

private static Response response;

private static Token tokenResponse;

private static Book book;

@Given("I am an authorized user")

public void iAmAnAuthorizedUser() {

AuthorizationRequest authRequest = new AuthorizationRequest("TOOLSQA-Test", "Test@@123");

response = Endpoints.authenticateUser(authRequest);

tokenResponse = response.getBody().as(Token.class);

@Given("A list of books are available")

public void listOfBooksAreAvailable() {

response = Endpoints.getBooks();

Books books = response.getBody().as(Books.class);

book = books.books.get(0);

@When("I add a book to my reading list")

public void addBookInList() {

ISBN isbn = new ISBN(book.isbn);

AddBooksRequest addBooksRequest = new AddBooksRequest(USER_ID, isbn);

response = Endpoints.addBook(addBooksRequest, tokenResponse.token);

@Then("The book is added")


Page | 224
public void bookIsAdded() {

Assert.assertEquals(201, response.getStatusCode());

UserAccount userAccount = response.getBody().as(UserAccount.class);

Assert.assertEquals(USER_ID, userAccount.userID);

Assert.assertEquals(book.isbn, userAccount.books.get(0).isbn);

@When("I remove a book from my reading list")

public void removeBookFromList() {

RemoveBookRequest removeBookRequest = new RemoveBookRequest(USER_ID, book.isbn);

response = Endpoints.removeBook(removeBookRequest, tokenResponse.token);

@Then("The book is removed")

public void bookIsRemoved() {

Assert.assertEquals(204, response.getStatusCode());

response = Endpoints.getUserAccount(USER_ID, tokenResponse.token);

Assert.assertEquals(200, response.getStatusCode());

UserAccount userAccount = response.getBody().as(UserAccount.class);

Assert.assertEquals(0, userAccount.books.size());

Run the Test

Run the Tests as JUnit

We are all set now to run the updated Cucumber test. Firstly, Right -Click on TestRunner class and Click Run
As >> JUnit Test. Cucumber will run the script in the same fashion as it runs in Selenium WebDriver. Finally, the
result will display in the left-hand side project explorer window in the JUnit tab.

Run the Tests from Cucumber Feature

Page | 225
To run the tests as a Cucumber Feature, right-click on the End2End_Test.feature file. After that, select the Run
As>>Cucumber Feature.

Moreover, our updated project folder structure of the framework will look likewise:

In the next chapter, we will introduce the Implementation of Routes in Endpoints in our API automation framework.
That would help us to make the framework maintainable and we won't have to make changes everywhere when the
route changes except for Routes class. Additionally, please implement the Endpoints class as discussed above, and
share your valuable feedback with us.

Implementation of REST Routes


In our previous chapter, we introduced the concept of using an Endpoints class in our framework. As a means to
abstract the logic of communication with the server into a separate class and to make our steps cleaner, we
introduced this Endpoints class. Subsequently, in this chapter, we are going to take it a step further by introducing
the REST Routes concept in our framework. As you all know, we use an API endpoint to carry out a specific task.
Moreover, Routes are the paths through which we can access the endpoints. In simpler terms, we call the route as
URI, while an endpoint is an action we perform on the URI.

What are REST Routes in API?


Page | 226
As we know, client-server communication is one of the REST (representational state transfer) principles. Additionally,
it provides a mapping between the HTTP verbs like GET, PUT, POST, DELETE, etc. with CRUD(create, read, update,
and delete) operations. We click on links and navigate through various sites. Moreover, in this process, we are
merely making a state transition when we navigate to one site from another. The REST-compliant systems are often
referred to as RESTful systems.

In addition to the above, the RESTful routes can be akin to a traditional pattern followed when structuring different
routes. It interacts with the server each time an HTTP request happens.

For example in the URL,

http://bookstore.toolsqa.com/BookStore/v1/Books:

BasePath: http://bookstore.toolsqa.com/

Route: /BookStore/v1/Books

Endpoint: There can be multiple tasks we can perform on this route. For example:

GET- http://bookstore.toolsqa.com/BookStore/v1/Books To fetch a list of books

POST- http://bookstore.toolsqa.com/BookStore/v1/Books To add a book associated with the user

DELETE - http://bookstore.toolsqa.com/BookStore/v1/Books To remove books associated with the user

It is how the endpoints looked in our Swagger Bookstore API

Implementation of REST Routes in Framework

We will follow the steps below to implement Routes in our framework:

1. Firstly, Create a Route class

2. Secondly, Modify the Endpoints class

3. Thirdly, Run the tests

Create a Route class

Let us add the Routes we discussed above in the first section to our Route class. We will keep all the routes at a
single place, and wherever the routes are required, we will use it from this class.

Moreover, the advantage it gives is that suppose any of the route changes. We won't have to make changes
everywhere. In other words, it's just at a single place in the Routes class.

1. Firstly, to create a Route class, Right-click on the apiEngine Package and select New >>Class. Name it
as Route.

2. After that, add the following code snippet to it:

package apiEngine;

public class Route {

Page | 227
private static final String BOOKSTORE = "/BookStore";

private static final String ACCOUNT = "/Account";

private static final String VERSION = "/v1";

public static String generateToken(){

return ACCOUNT + VERSION + "/GenerateToken";

public static String books(){

return BOOKSTORE + VERSION + "/Books";

public static String book(){

return BOOKSTORE + VERSION + "/Book";

public static String userAccount(String userId){

return ACCOUNT + VERSION + "/User" + "/" + userId;

Modify the Endpoints class for REST Routes

We will modify the methods in the endpoints class. Additionally, we will pass the routes from the Routes class
instead of writing them to a specific route in the method itself.

For Example:

Our method authenticateUser() is updated from:

public static Response authenticateUser(AuthorizationRequest authRequest) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

//The hardcoded route "/Account/vi/GenerateToken" will be modified to take the route from the Route class

Response response = request.body(authRequest).post("/Account/v1/GenerateToken");

return response;

to

public static Response authenticateUser(AuthorizationRequest authRequest) {

RestAssured.baseURI = BASE_URL;

Page | 228
RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.body(authRequest).post(Route.generateToken());

return response;

Explanation:

In this method, the route for generating token is now taken from the Route class instead of passing the
route "/Account/v1/GenerateToken".

Similarly, we update the below methods for the Endpoints class:

1. getBooks()

2. addBook()

3. removeBook()

4. getUserAccount()

Consequently, our updated Endpoints class will look likewise:

package apiEngine;

import apiEngine.model.requests.AddBooksRequest;

import apiEngine.model.requests.AuthorizationRequest;

import apiEngine.model.requests.RemoveBookRequest;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class EndPoints {

private static final String BASE_URL = "https://bookstore.toolsqa.com";

public static Response authenticateUser(AuthorizationRequest authRequest) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.body(authRequest).post(Route.generateToken());

Page | 229
return response;

public static Response getBooks() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.get(Route.books());

return response;

public static Response addBook(AddBooksRequest addBooksRequest, String token) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

Response response = request.body(addBooksRequest).post(Route.books());

return response;

public static Response removeBook(RemoveBookRequest removeBookRequest, String token) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

Response response = request.body(removeBookRequest).delete(Route.book());

return response;

Page | 230
public static Response getUserAccount(String userId, String token) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

Response response = request.get(Route.userAccount(userId));

return response;

Run the Cucumber Test

Run the Tests as JUnit

We are all set now to run the updated Cucumber test. First, Right -Click on the TestRunner class. Secondly, Click Run
As >> JUnit Test. Finally, the result will display in the JUnit tab of the console.

Run the Tests from Cucumber Feature

To run the tests as a Cucumber Feature, right-click on the End2End_Test.feature file. After that, select the Run
As>>Cucumber Feature.

Page | 231
Our tests passed with the changes we made for the Rest Routes implementation in our framework. Our updated
project folder structure of the framework will look likewise:

Subsequently, in the next chapter, we will implement generics in our framework to handle response objects of
various data types. Meanwhile, please try and apply the above changes in your framework, as explained.

Implementation of Generics in API Framework


In the previous chapter, we introduced the concept of using REST Routes in our Endpoints class for the framework.
In case if the route changes, we won't have to make changes everywhere, it's just at a single place in the Routes
class.

Subsequently, in this chapter, we are going to implement the Generics concept in our framework. We are dealing
with the response objects of various data types such as Token, Books, and User Account. Moreover, one can build
these response objects fail-safe by using generics. Generics adds a layer of abstraction. In addition to that, they add a
way to specify types for classes and methods. You can read more about the Generics concept in this Generics
tutorial. In this article, we are going to cover:-

• What is the need for a Generics class implementation?

• Implementation of Generics

What is the need for a Generics class implementation

Consider an example of returning a Book object from Endpoint method like below:

public static Books getBooks() {

RequestSpecification request = RestAssured.given();

Response response = request.get(Route.books());

return response.getBody().as(Books.class);

If we would get a failed response, our code will fail in the above method implementation.

So supposedly if we were to handle the failure like below:

public static Books getBooks() {

RequestSpecification request = RestAssured.given();

Response response = request.get(Route.books());

Page | 232
int code = response.getStatusCode();

if( code == 200 || code == 201 || code == 202 || code == 203 || code == 204 || code == 205) {

return response.getBody().as(Book.Class());

we would not be able to test negative tests by sending a wrong body and expecting a 204. We would likely be stuck
in such a case.

Thus we need a class, which will return the Response Body as well as status and in case of failure return exception or
error message.

Now, the response received from the server can be of several data types. Hence, we need an interface capable of
handling different response objects. To provide this parameterized value to a parameterized type, we implement
this as a Generic Interface. This interface will contain all the methods we need when we operate on
a REST Response.

Implementation of Generics

We will follow the steps below to implement Generics in our framework:

1. Create a Generic Interface

2. Create a class to implement generic interface methods

3. Modification of the Endpoints class

4. Modification of Steps class

5. Run the tests

Create a Generic Interface

Firstly, right-click on the apiEngine package and select New >> Interface. Name it as IRestResponse.

IRestResponse.java

package apiEngine;

import io.restassured.response.Response;

public interface IRestResponse<T>{

public T getBody();

public String getContent();

public int getStatusCode();

public boolean isSuccessful();

public String getStatusDescription();

public Response getResponse();

Page | 233
public Exception getException();

Explanation:

We created a generic interface of type <T>. Thus, we can use this interface to hold responses of different types. For
example, IRestResponse<Books> will hold the response of type Books. Likewise, it will be for
IRestResponse<UserAccount> and IRestResponse<Token>.

Note: As explained above, we need this interface to return the Body as well as status, and in case of failure return
exception or error message. Therefore, that's why we have those attributes in the interface.

Create a class to implement generic interface methods

We defined the methods we need to operate on the REST response. We need to apply these methods next in our
Rest Response class.

Right-click on the apiEngine package and select New >> Class. Name it as RestResponse.

package apiEngine;

import io.restassured.response.Response;

public class RestResponse<T> implements IRestResponse<T> {

private T data;

private Response response;

private Exception e;

public RestResponse(Class<T> t, Response response) {

this.response = response;

try{

this.data = t.newInstance();

}catch (Exception e){

throw new RuntimeException("There should be a default constructor in the Response


POJO");

public String getContent() {

return response.getBody().asString();

Page | 234
public int getStatusCode() {

return response.getStatusCode();

public boolean isSuccessful() {

int code = response.getStatusCode();

if( code == 200 || code == 201 || code == 202 || code == 203 || code == 204 || code == 205) return
true;

return false;

public String getStatusDescription() {

return response.getStatusLine();

public Response getResponse() {

return response;

public T getBody() {

try {

data = (T) response.getBody().as(data.getClass());

}catch (Exception e) {

this.e=e;

return data;

public Exception getException() {

return e;

Page | 235
Explanation:

We implemented the methods to return us relevant details of REST responses as needed for testing.

• isSuccessful(): Will validate if the sending request was successful. It validates the response status code
received against the numerous HTTP status codes denoting that request was successfully processed

• getResponse().getBody().asString(): We will need the response body content in String format at times. This
method implementation takes care of it.

• getException(): In case our response body is not deserialized successfully, we will get an exception. e will
contain this exception, which we get using this method.

Modification of Endpoints class

Our methods for Endpoints class will change. They will return responses of the type RestResponse<Books>,
RestResponse<Token> and RestResponse<UserAccount> for the respective methods.

For Example: Our method authenticateUser() is updated from:

public static Response authenticateUser(AuthorizationRequest authRequest) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.body(authRequest).post(Route.generateToken());

return response;

to

public static IRestResponse<Token> authenticateUser(AuthorizationRequest authRequest) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.body(authRequest).post(Route.generateToken());

return new RestResponse(Token.class, response);

Explanation:

In this method, we have wrapped the Rest Assured Response into our RestResponse class of the type Token, where
we have deserialized the responses.

Similarly, we updated the below methods for the Endpoints class:

1. getBooks()

2. addBook()

Page | 236
3. removeBook()

4. getUserAccount()

Our updated Endpoints class will look likewise:

package apiEngine;

import apiEngine.model.requests.AddBooksRequest;

import apiEngine.model.requests.AuthorizationRequest;

import apiEngine.model.requests.RemoveBookRequest;

import apiEngine.model.responses.Books;

import apiEngine.model.responses.Token;

import apiEngine.model.responses.UserAccount;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class EndPoints {

private static final String BASE_URL = "https://bookstore.toolsqa.com";

public static IRestResponse<Token> authenticateUser(AuthorizationRequest authRequest) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.body(authRequest).post(Route.generateToken());

return new RestResponse(Token.class, response);

public static IRestResponse<Books> getBooks() {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Content-Type", "application/json");

Response response = request.get(Route.books());


Page | 237
return new RestResponse(Books.class, response);

public static IRestResponse<UserAccount> addBook(AddBooksRequest addBooksRequest, String token) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

Response response = request.body(addBooksRequest).post(Route.books());

return new RestResponse(UserAccount.class, response);

public static Response removeBook(RemoveBookRequest removeBookRequest, String token) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

return request.body(removeBookRequest).delete(Route.book());

public static IRestResponse<UserAccount> getUserAccount(String userId, String token) {

RestAssured.baseURI = BASE_URL;

RequestSpecification request = RestAssured.given();

request.header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

Response response = request.get(Route.userAccount(userId));

return new RestResponse(UserAccount.class, response);


Page | 238
}

Modification of Steps class

We will modify the step definitions to call the methods listed in the endpoints class.

Moreover, you will directly obtain the response in the step definition class. As already explained, the logic of
communication with the server and converting it into the response class moves out. Thus, our step definition
consists of only the testing layer which we are interested in and not the internal workings of the API.

Our updated step definition file would look like:

package stepDefinitions;

import apiEngine.EndPoints;

import apiEngine.IRestResponse;

import apiEngine.model.*;

import apiEngine.model.requests.*;

import apiEngine.model.responses.*;

import org.junit.Assert;

import cucumber.api.java.en.Given;

import cucumber.api.java.en.Then;

import cucumber.api.java.en.When;

import io.restassured.response.Response;

public class Steps {

private static final String USER_ID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";

private static Response response;

private static Token tokenResponse;

private static IRestResponse<UserAccount> userAccountResponse;

private static Book book;

@Given("^I am an authorized user$")

public void iAmAnAuthorizedUser() {

Page | 239
AuthorizationRequest authRequest = new AuthorizationRequest("TOOLSQA-Test", "Test@@123");

tokenResponse = EndPoints.authenticateUser(authRequest).getBody();

@Given("^A list of books are available$")

public void listOfBooksAreAvailable() {

IRestResponse<Books> booksResponse = EndPoints.getBooks();

book = booksResponse.getBody().books.get(0);

@When("^I add a book to my reading list$")

public void addBookInList() {

ISBN isbn = new ISBN(book.isbn);

AddBooksRequest addBooksRequest = new AddBooksRequest(USER_ID, isbn);

userAccountResponse = EndPoints.addBook(addBooksRequest, tokenResponse.token);

@Then("^The book is added$")

public void bookIsAdded() {

Assert.assertTrue(userAccountResponse.isSuccessful());

Assert.assertEquals(201, userAccountResponse.getStatusCode());

Assert.assertEquals(USER_ID, userAccountResponse.getBody().userID);

Assert.assertEquals(book.isbn, userAccountResponse.getBody().books.get(0).isbn);

@When("^I remove a book from my reading list$")

public void removeBookFromList() {

RemoveBookRequest removeBookRequest = new RemoveBookRequest(USER_ID, book.isbn);

response = EndPoints.removeBook(removeBookRequest, tokenResponse.token);

@Then("^The book is removed$")

public void bookIsRemoved() {


Page | 240
Assert.assertEquals(204, response.getStatusCode());

userAccountResponse = EndPoints.getUserAccount(USER_ID, tokenResponse.token);

Assert.assertEquals(200, userAccountResponse.getStatusCode());

Assert.assertEquals(0, userAccountResponse.getBody().books.size());

Run the Cucumber Test

Run the Tests as JUnit

We are all set now to run the updated Cucumber test. Right -Click on TestRunner class and Click Run As >> JUnit
Test. Consequently, you will see the result in the left-hand side project explorer window in the JUnit tab.

Run the Tests from Cucumber Feature

To run the tests as a Cucumber Feature, right-click on the End2End_Test.feature file. After that, select the Run
As>>Cucumber Feature.

Our updated project folder structure of the framework will look likewise:

Page | 241
Our tests passed with the changes we made for the Generics implementation in our framework. We will
be Refactoring for Request Headers so that we can make use of a single request object in our next chapter.
Moreover, it will avoid the complexity of adding the auth header repeatedly for each request.

Meanwhile, please try to implement the above changes in your framework, as explained above.

Refactoring for Request Headers


In the previous chapter, we introduced the usage of Generics for the Endpoints class of our application framework. It
helped us to handle different response objects we get. In this chapter, we will change the static
methods of Endpoints.java class into instance methods and work on Refactoring Request Headers. It is also
important to understand the difference between the Static and Instance Method in programming.

By converting the EndPoint class into an Instance class, it will help us to make use of a Single Request Object. It will
save us the trouble of adding the request header each time we pass the request. Here are the topics which we are
going to cover in this article:-

• Need for Refactoring Request Headers

• Steps for Refactoring Request Headers

o Convert static methods into instance methods

o Update the Steps file

o Run the tests

So let's get started.

Need for Refactoring Request Headers

Consider the methods from the below image of Endpoints.java class:

Page | 242
We are sending this highlighted piece of code - the BASE_URL, the headers in every method, as we call our methods
in the Step Definitions. It leads to us creating the RequestSpecification object again and again when it is the same for
every step. It would be simpler if we created this once for all the steps.

If one uses the static methods, it causes random failures in the tests as they turn flaky if the tests run in parallel in
the future course. Every thread tries to access the available static resource. During this, the thread could come in a
situation where another thread is in a position to access the same static resources. Thus, to avoid the test failures
during parallel execution.

To achieve this, we will need to initialize the RequestSpecification object in the constructor. Therefore now we will
need to make all these methods in Endpoints.java class as non-static.

But what we would achieve from this for the framework? Once the authentication is set in the
RequestSpecification object, it is good for all the subsequent requests. It is not required to set it again during the
next request.

Let's see how to do this.

Steps for Refactoring Request Headers

To refactor the existing code to create just a single request object, we follow these steps:

1. Convert static methods into instance methods

2. Update the Steps file

3. Run the tests

So let's begin with our first step.

Convert Static Methods into Instance Methods

The changes in the Endpoints.java class would be:

package apiEngine;
Page | 243
import org.apache.http.HttpStatus;

import apiEngine.model.requests.AddBooksRequest;

import apiEngine.model.requests.AuthorizationRequest;

import apiEngine.model.requests.RemoveBookRequest;

import apiEngine.model.responses.Books;

import apiEngine.model.responses.Token;

import apiEngine.model.responses.UserAccount;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class EndPoints {

private final RequestSpecification request;

public EndPoints(String baseUrl) {

RestAssured.baseURI = baseUrl;

request = RestAssured.given();

request.header("Content-Type", "application/json");

public void authenticateUser(AuthorizationRequest authRequest) {

Response response = request.body(authRequest).post(Route.generateToken());

if (response.statusCode() != HttpStatus.SC_OK)

throw new RuntimeException("Authentication Failed. Content of failed Response: " + response.toString() + " ,
Status Code : " + response.statusCode());

Token tokenResponse = response.body().jsonPath().getObject("$", Token.class);

request.header("Authorization", "Bearer " + tokenResponse.token);

public IRestResponse<Books> getBooks() {

Page | 244
Response response = request.get(Route.books());

return new RestResponse(Books.class, response);

public IRestResponse<UserAccount> addBook(AddBooksRequest addBooksRequest) {

Response response = request.body(addBooksRequest).post(Route.books());

return new RestResponse(UserAccount.class, response);

public Response removeBook(RemoveBookRequest removeBookRequest) {

return request.body(removeBookRequest).delete(Route.book());

public IRestResponse<UserAccount> getUserAccount(String userId) {

Response response = request.get(Route.userAccount(userId));

return new RestResponse(UserAccount.class, response);

Code Explanation:

As you can see in the above code, we have created a constructor which takes care of initializing
the RequestSpecification object with baseURL and Request Headers in the constructor when the Endpoints class
initializes in the Steps file.

We also need token to be passed as well in request Header. For that in the method authenticateUser() when we
get tokenResponse, we set it in the same instance of request. This header will then be available when we make
subsequent calls to the server. Since authenticating the user will always be the first step, we will not need to add the
token in the header for every request we make after that.

Update the Steps file for the above change

Our Steps file too would change as per the Endpoints.java class

package stepDefinitions;

import apiEngine.EndPoints;

import apiEngine.IRestResponse;

import apiEngine.model.*;

import apiEngine.model.requests.*;

Page | 245
import apiEngine.model.responses.*;

import org.junit.Assert;

import cucumber.api.java.en.Given;

import cucumber.api.java.en.Then;

import cucumber.api.java.en.When;

import io.restassured.response.Response;

public class Steps {

private final String USER_ID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";

private Response response;

private IRestResponse<UserAccount> userAccountResponse;

private Book book;

private final String BaseUrl = "https://bookstore.toolsqa.com";

private EndPoints endPoints;

@Given("^I am an authorized user$")

public void iAmAnAuthorizedUser() {

endPoints = new EndPoints(BaseUrl);

AuthorizationRequest authRequest = new AuthorizationRequest("TOOLSQA-Test", "Test@@123");

endPoints.authenticateUser(authRequest);

@Given("^A list of books are available$")

public void listOfBooksAreAvailable() {

IRestResponse<Books> booksResponse = endPoints.getBooks();

book = booksResponse.getBody().books.get(0);

@When("^I add a book to my reading list$")

public void addBookInList() {

ISBN isbn = new ISBN(book.isbn);

AddBooksRequest addBooksRequest = new AddBooksRequest(USER_ID, isbn);


Page | 246
userAccountResponse = endPoints.addBook(addBooksRequest);

@Then("^The book is added$")

public void bookIsAdded() {

Assert.assertTrue(userAccountResponse.isSuccessful());

Assert.assertEquals(201, userAccountResponse.getStatusCode());

Assert.assertEquals(USER_ID, userAccountResponse.getBody().userID);

Assert.assertEquals(book.isbn, userAccountResponse.getBody().books.get(0).isbn);

@When("^I remove a book from my reading list$")

public void removeBookFromList() {

RemoveBookRequest removeBookRequest = new RemoveBookRequest(USER_ID, book.isbn);

response = endPoints.removeBook(removeBookRequest);

@Then("^The book is removed$")

public void bookIsRemoved() {

Assert.assertEquals(204, response.getStatusCode());

userAccountResponse = endPoints.getUserAccount(USER_ID);

Assert.assertEquals(200, userAccountResponse.getStatusCode());

Assert.assertEquals(0, userAccountResponse.getBody().books.size());

Code Explanation:

Page | 247
We have initialized an Endpoints class object-endpoints and passed the baseURL in the
step iAmAnAuthorizedUser() by invoking a constructor of Endpoints class. Also, this same endpoint object is being
used by all the step definitions instead of calling static Endpoint methods.

Run the tests

We are all set now to run the updated Cucumber test. Subsequently, we will Right-Click on the TestRunner class.
After that, we will Click Run As >> JUnit Test. Consequently, the result will appear in the left-hand side project
explorer window in the JUnit tab.

Run the Tests from Cucumber Feature

To run the tests as a Cucumber Feature, right-click on the End2End_Test.feature file. Select the Run As>>Cucumber
Feature.

Our updated project folder structure of the framework will look likewise:

Page | 248
Our tests passed with the changes we made for the Refactoring of the Request Headers in our framework. We
will learn to share Test Context between our Step Definitions so that we can have the step definition file uncluttered
and share the Test Context with all the Step Definition files. It will avoid the complexity of adding the auth header
repeatedly for each request.

Share Test Context in Cucumber


In our previous chapter, we refactored the endpoints class to pass the Request headers as an instance of Endpoints
class instead of passing them in each method. Subsequently, as a next step, we will learn to Share Test Context
between our Step Definitions in our API Rest Assured Automation Framework.

Need for Sharing the Test Context between Cucumber Step Definitions

In real-life projects, the expectation is we build a scalable automation framework. Moreover, automation coverage
increases as we add multiple scenarios. If a single step definition file contains all the step definitions, it clutters the
step definition file. Additionally, it becomes non-maintainable. It is thus, imperative to refactor the step definitions
separated under different classes.

In any scenario of a feature file in Cucumber, a series of steps get executed one after one. Every step of the scenario
may possess a state which could prove useful to another step in the same scenario. Thus, the steps depend on the
previously executed steps. Moreover, for this reason, sharing the state among the steps is needed.

In our framework, we have just one scenario for illustration purposes. But, it will grow over a while as we add
numerous scenarios. Additionally, to keep the step definition file uncluttered and share the Test Context with all
the Step Definition files, we will resort to the dependency injection Container PicoContainer. We have implemented
this before in our former Cucumber tutorial with Selenium on sharing Test Context with Cucumber Step Definitions.

As a next step, we will learn the way to implement the Test Context sharing between our Step Definitions in our API
Rest Assured Automation Framework.

How to Share the Test Context between Cucumber Steps using PicoContainer

We will follow the same steps as sharing Test Context with Cucumber Step Definitions to share the data state across
steps:

1. Firstly, add PicoContainer to the Project.

2. Secondly, create a Test Context class to hold all the objects state.

3. Thirdly, divide the Steps class into multiple steps classes.

4. Fourth, write Constructor to share Test Context.

5. Finally, run the Tests.

Add PicoContainer Library to the Maven Project

Add the maven dependency of dependency injection-PicoContainer into our project pom.xml. Additionally, you can
find more details about the version etc. at [Maven Repository - Cucumber PicoContainer]

(https://mvnrepository.com/artifact/io.cucumber/cucumber-picocontainer).

<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-picocontainer -->

<dependency>

<groupId>io.cucumber</groupId>

<artifactId>cucumber-picocontainer</artifactId>

Page | 249
<version>5.5.0</version>

<scope>test</scope>

</dependency>

Create a Test Context class which will hold all the objects state

The Text Context class shall encompass all information your Steps files are using. In our framework, we are likewise
using the information from the Endpoints class in the Steps file. So simply, we need to add an object of Endpoints
class into this Test Context class.

To create a Test Context class,

1. Firstly, Right-click on the src/test/java and select New >> Package. Moreover, name it as a cucumber. All
the Cucumber Helper classes will be in the same package hereon.

2. Secondly, Right-click on the above-created package and select New >> Class. Name it as TestContext.

TestContext.java

package cucumber;

import apiEngine.EndPoints;

public class TestContext {

private String BASE_URL = "https://bookstore.toolsqa.com";

private EndPoints endPoints;

public TestContext() {

endPoints = new EndPoints(BASE_URL);

public EndPoints getEndPoints() {

return endPoints;

Consequently, we kept the initialization of Endpoints in the constructor and created getEndPoints() for the object.

Divide the Steps class into multiple steps classes

We can logically divide our endpoints into Account Steps and Book Steps. Some of the necessary steps would include
in the BaseStep.

Create three New Classes in the stepDefinitions package with the following names:

• AccountSteps

Page | 250
• BooksSteps

• BaseStep

Note: You may replace the Steps file with BaseSteps during clean up by moving the required step definitions to
associated classes. Alternatively, you can create a BaseStep class, and once we completed this tutorial, then delete
the Steps file as we no longer would be using it.

Write Constructor to share Test Context

We divided the Step Definitions to different Step classes. These classes commonly share the Endpoints class amongst
themselves. Additionally, in real-life projects, we may have such multiple classes that have an extensive requirement
for every Step class. Moreover, to create objects for all standard classes using a new operator, again and again, is not
advisable.

If we add a constructor to our Steps class file and pass TestContext as a Parameter to the constructor, it would solve
all the problems. In the TestContext object, we got everything required for the test.

Thus the AccountsSteps.java class will look as:

package stepDefinitions;

import apiEngine.model.requests.*;

import cucumber.TestContext;

import cucumber.api.java.en.Given;

public class AccountSteps extends BaseStep {

public AccountSteps(TestContext testContext){

super(testContext);

@Given("^I am an authorized user$")

public void iAmAnAuthorizedUser() {

AuthorizationRequest authRequest = new AuthorizationRequest("TOOLSQA-Test", "Test@@123");

getEndPoints().authenticateUser(authRequest);

Likewise, the changes for BooksSteps.java class is:

package stepDefinitions;

import apiEngine.IRestResponse;
Page | 251
import apiEngine.model.Book;

import apiEngine.model.requests.AddBooksRequest;

import apiEngine.model.requests.ISBN;

import apiEngine.model.requests.RemoveBookRequest;

import apiEngine.model.responses.Books;

import apiEngine.model.responses.UserAccount;

import cucumber.TestContext;

import cucumber.api.java.en.Given;

import cucumber.api.java.en.Then;

import cucumber.api.java.en.When;

import io.restassured.response.Response;

import org.junit.Assert;

public class BooksSteps extends BaseStep {

public BooksSteps(TestContext testContext){

super(testContext);

private final String USER_ID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";

private Response response;

private IRestResponse<UserAccount> userAccountResponse;

private Book book;

@Given("^A list of books are available$")

public void listOfBooksAreAvailable() {

IRestResponse<Books> booksResponse = getEndPoints().getBooks();

book = booksResponse.getBody().books.get(0);

@When("^I add a book to my reading list$")

public void addBookInList() {

ISBN isbn = new ISBN(book.isbn);

AddBooksRequest addBooksRequest = new AddBooksRequest(USER_ID, isbn);


Page | 252
userAccountResponse = getEndPoints().addBook(addBooksRequest);

@Then("^The book is added$")

public void bookIsAdded() {

Assert.assertTrue(userAccountResponse.isSuccessful());

Assert.assertEquals(201, userAccountResponse.getStatusCode());

Assert.assertEquals(USER_ID, userAccountResponse.getBody().userID);

Assert.assertEquals(book.isbn, userAccountResponse.getBody().books.get(0).isbn);

@When("^I remove a book from my reading list$")

public void removeBookFromList() {

RemoveBookRequest removeBookRequest = new RemoveBookRequest(USER_ID, book.isbn);

response = getEndPoints().removeBook(removeBookRequest);

@Then("^The book is removed$")

public void bookIsRemoved() {

Assert.assertEquals(204, response.getStatusCode());

userAccountResponse = getEndPoints().getUserAccount(USER_ID);

Assert.assertEquals(200, userAccountResponse.getStatusCode());

Assert.assertEquals(0, userAccountResponse.getBody().books.size());

Lastly, the BaseSteps.java class updates as:

package stepDefinitions;

import apiEngine.EndPoints;

import cucumber.TestContext;

Page | 253
public class BaseStep {

private static final String BASE_URL = "https://bookstore.toolsqa.com";

private EndPoints endPoints;

public BaseStep(TestContext testContext) {

endPoints = testContext.getEndPoints();

public EndPoints getEndPoints() {

return endPoints;

Run the Cucumber Test

Run the Tests as JUnit

We are all set now to run the updated Cucumber test. First, Right -Click on TestRunner class and Click Run
As >> JUnit Test. Cucumber runs the script in the same way as Selenium WebDriver. Consequently, the result will
display in the JUnit tab of the console.

Run the Tests from Cucumber Feature

To run the tests as a Cucumber Feature, right-click on the End2End_Test.feature file. After that, select the Run
As>>Cucumber Feature.

Page | 254
The tests passed successfully with the changes we made for sharing the Test Context with Cucumber Step
Definitions in our framework. Please try to implement the above changes in your framework, as explained above.

Our updated project folder structure of the framework will look likewise:

In the next chapter, we will introduce the concept of usage of Scenario Context in Framework to share the test data
information specifically. Additionally, we will further segregate our steps into the Verification Steps from the Step
classes.

Share Scenario Context in Cucumber


In the previous chapter, we implemented a Sharing Test Context between Cucumber Steps. Additionally, we made
the changes to make the step definition file uncluttered and share the Test Context with all the Step Definition files.
In continuation of the earlier chapter, we will now proceed to Share Data by using Scenario Context in Cucumber.

Scenario Context class holds the test data information explicitly. It helps you store values in a key-value pair
between the steps. Moreover, it helps in organizing step definitions better rather than using private variables in step
definition classes. We have implemented this before in our previous Cucumber tutorial on sharing data between
steps in Cucumber using Scenario Context.

As a next step, we are going to implement the Scenario Context in cucumber for sharing data between our Step
Definitions in our API Rest Assured Automation Framework.

Share Scenario Context in Cucumber

In the end-to-end tests, you're interested in verifying the response for the requests sent. Let’s say you wish to check
the subsequent actions within the tests:

Page | 255
• Addition of Book

• Removal of Book

In that case, we want to store the book details in Scenario Context object while adding the book to the user account.
Likewise, in our next verification step, we remove the book from the user account. Moreover, we retrieve from
the ScenarioContext, book details of the added book, and validate its removal from the user account.

We will follow the identical steps as sharing Scenario Context with Cucumber Step Definitions to share the test data
information state across steps:

1. Firstly, create a Scenario Context class.

2. Secondly, save the test information state within the Scenario Context.

3. Thirdly, add a Verification Step file to Test for Responses.

4. Fourthly, run the Cucumber Test.

Step 1: Create a Scenario Context class

It is a clean code practice to create enums for all the fixed set of values in the project.

1. Firstly, Right-click on the src/test/java and select New >> Package. Moreover, name it as enums. We will
keep all the project enums in this package.

2. Secondly, Right-click on the enums package and select New >> Enum. Name it as Context. Moreover, we will
add our enum in it.

Context.java

package enums;

public enum Context {

BOOK,

USER_ID,

USER_ACCOUNT_RESPONSE,

BOOK_REMOVE_RESPONSE;

3. After that, Right-click on the cucumber package and select New >> Class. Name it as ScenarioContext.

package cucumber;

import enums.Context;

import java.util.HashMap;

import java.util.Map;

public class ScenarioContext {

Page | 256
private Map<String, Object> scenarioContext;

public ScenarioContext(){

scenarioContext = new HashMap<String, Object>();

public void setContext(Context key, Object value) {

scenarioContext.put(key.toString(), value);

public Object getContext(Context key){

return scenarioContext.get(key.toString());

public Boolean isContains(Context key){

return scenarioContext.containsKey(key.toString());

Code Explanation:

• scenarioContext: It's a HashMap object storing the information in the Key-Value pair. The key type is String.
Moreover, theValue can be of any Object Type.

• setContext(): This method takes two parameters, key as Context and value as an object. Key is nothing but
a Context enum.

• getContext(): This method takes a key as a parameter to returns the object matching the key.

• isContains(): This method checks in the complete Map if the respective key exists or not.

4. Fourthly, include ScenarioContext in TextContext. It will ensure that ScenarioContext is shared across all the
Cucumber Steps using the Pico-Container library. We added in our previous chapter. Moreover, add
a getter method as getScenarioContext() to get the scenarioContext object.

TestContext.java

package cucumber;

import apiEngine.EndPoints;

import enums.Context;

Page | 257
public class TestContext {

private final String BASE_URL = "https://bookstore.toolsqa.com";

private final String USER_ID = "9b5f49ab-eea9-45f4-9d66-bcf56a531b85";

private EndPoints endPoints;

private ScenarioContext scenarioContext;

public TestContext() {

endPoints = new EndPoints(BASE_URL);

scenarioContext = new ScenarioContext();

scenarioContext.setContext(Context.USER_ID, USER_ID);

public EndPoints getEndPoints() {

return endPoints;

public ScenarioContext getScenarioContext() {

return scenarioContext;

Also, the BaseSteps.java class updates as:

package stepDefinitions;

import apiEngine.EndPoints;

import cucumber.ScenarioContext;

import cucumber.TestContext;

public class BaseStep {

private EndPoints endPoints;


Page | 258
private ScenarioContext scenarioContext;

public BaseStep(TestContext testContext) {

endPoints = testContext.getEndPoints();

scenarioContext = testContext.getScenarioContext();

public EndPoints getEndPoints() {

return endPoints;

public ScenarioContext getScenarioContext() {

return scenarioContext;

Step 2: Save the test information state in the Scenario Context

In this step, we save the responses of our requests to ScenarioContext object. To begin with, we will add the book to
the reading list of the user and save our response. Subsequently, the responses will then validate in our assertions as
a part of the verification steps.

In the below steps of the BooksSteps.java class, we are saving responses to scenario context objects.

BooksSteps.java

package stepDefinitions;

import apiEngine.IRestResponse;

import apiEngine.model.Book;

import apiEngine.model.requests.AddBooksRequest;

import apiEngine.model.requests.ISBN;

import apiEngine.model.requests.RemoveBookRequest;

import apiEngine.model.responses.Books;

import apiEngine.model.responses.UserAccount;

import cucumber.TestContext;

import cucumber.api.java.en.Given;

import cucumber.api.java.en.When;

import enums.Context;

Page | 259
import io.restassured.response.Response;

public class BooksSteps extends BaseStep {

public BooksSteps(TestContext testContext) {

super(testContext);

@Given("^A list of books are available$")

public void listOfBooksAreAvailable() {

IRestResponse<Books> booksResponse = getEndpoints().getBooks();

Book book = booksResponse.getBody().books.get(0);

getScenarioContext().setContext(Context.BOOK, book);

@When("^I add a book to my reading list$")

public void addBookInList() {

Book book = (Book) getScenarioContext().getContext(Context.BOOK);

String userId = (String) getScenarioContext().getContext(Context.USER_ID);

ISBN isbn = new ISBN(book.isbn);

AddBooksRequest addBooksRequest = new AddBooksRequest(userId, isbn);

IRestResponse<UserAccount> userAccountResponse = getEndpoints().addBook(addBooksRequest);

getScenarioContext().setContext(Context.USER_ACCOUNT_RESPONSE, userAccountResponse);

@When("^I remove a book from my reading list$")

public void removeBookFromList() {

Book book = (Book) getScenarioContext().getContext(Context.BOOK);

String userId = (String) getScenarioContext().getContext(Context.USER_ID);

RemoveBookRequest removeBookRequest = new RemoveBookRequest(userId, book.isbn);

Page | 260
Response response = getEndpoints().removeBook(removeBookRequest);

getScenarioContext().setContext(Context.BOOK_REMOVE_RESPONSE, response);

Step 3: Add a Verification Step file to Test for Responses

We will verify the responses saved in our ScenarioContext Objects as a part of this step. We will move all our
verification steps to a new class created as VerificationSteps.java.

Create a New Class and name it as VerificationSteps, by right-clicking on the stepDefinitions. After that, select New
>> Class.

VerificationSteps.java

package stepDefinitions;

import apiEngine.IRestResponse;

import apiEngine.model.Book;

import apiEngine.model.responses.UserAccount;

import cucumber.TestContext;

import cucumber.api.java.en.Then;

import enums.Context;

import io.restassured.response.Response;

import org.junit.Assert;

public class VerificationSteps extends BaseStep {

public VerificationSteps(TestContext testContext) {

super(testContext);

@Then("^The book is added$")

public void bookIsAdded() {

Book book = (Book) getScenarioContext().getContext(Context.BOOK);

String userId = (String) getScenarioContext().getContext(Context.USER_ID);

IRestResponse<UserAccount> userAccountResponse = (IRestResponse<UserAccount>)


getScenarioContext().getContext(Context.USER_ACCOUNT_RESPONSE);

Page | 261
Assert.assertTrue(userAccountResponse.isSuccessful());

Assert.assertEquals(201, userAccountResponse.getStatusCode());

Assert.assertEquals(userId, userAccountResponse.getBody().userID);

Assert.assertEquals(book.isbn, userAccountResponse.getBody().books.get(0).isbn);

@Then("^The book is removed$")

public void bookIsRemoved() {

String userId = (String) getScenarioContext().getContext(Context.USER_ID);

Response response = (Response) getScenarioContext().getContext(Context.BOOK_REMOVE_RESPONSE);

Assert.assertEquals(204, response.getStatusCode());

IRestResponse<UserAccount> userAccountResponse = getEndPoints().getUserAccount(userId);

Assert.assertEquals(200, userAccountResponse.getStatusCode());

Assert.assertEquals(0, userAccountResponse.getBody().books.size());

Explanation

• We just need to pass the Key to the getContext() method, which we can access
like scenarioContext.getContext(Key Name). Additionally, it will retrieve the value returned by the response
for Book.

• Since the method returns an object, we need to cast it to the right type. If it's cast it to a wrong type, the test
will fail here. So, we must be sure of the object type we stored for the respective key.

Step 4: Run the Cucumber Test

Run the Tests as JUnit

We are all set now to run the updated Cucumber test. Firstly, Right -Click on TestRunner class and Click Run
As >> JUnit Test. Cucumber runs the script in the same way as Selenium WebDriver. Consequently, the result will
display in the JUnit tab of the console.

Page | 262
Run the Tests from Cucumber Feature

To run the tests as a Cucumber Feature, right-click on the End2End_Test.feature file. Select the Run As>>Cucumber
Feature.

The tests passed successfully with the changes we made for sharing test data in Cucumber Steps using Scenario
Context in our framework.

Our updated project folder structure of the framework will look likewise:

In the next chapter, we will add Config Reader class for BaseUrl and UserId. Please try to implement the above
changes in your framework, as explained above.

Implement Configuration Reader


In our previous chapter, we accomplished the sharing of test data in Cucumber Steps using Scenario Context.
Subsequently, in this cImplement Configuration Readerhapter, we shall read the configuration values from a
property file and use them in our code with the help of Configuration Reader.
Page | 263
If you may have noticed, so far, we are passing the user_Idand the base_Url values as hardcoded ones. However, the
problem with hardcoded values is that they are non-maintainable. In other words, the changes in configuration value
amount to making changes in several places in the code. Therefore, it is not a clean code practice.

As a solution to this, we will go for property file implementation in Java. If you wish to understand this on a
conceptual level, you could refer to the Read Configurations from Property File. Let us learn how to implement the
configurations from the property file.

Implement Configuration Reader to Read Project Configurations

We will follow the below steps and implement Read Configurations:

1. How to Read Configurations from Property File

2. Write Hard-Coded Values in the Property File

3. Create a Configuration Reader File

4. Use ConfigFileReader object in the TestContext file

5. Run the Cucumber Test

How to Read Configurations from Property File

Firstly, right-click on the root Project and select New >> Folder. Additionally, name it as configs. Moreover, we will
keep config files with in the same folder.

Secondly, right-click the above-created folder and select New >> File. Additionally, name it
as configuration.properties. Here, the .properties is the file extension.

Page | 264
Step 2: Write Hard-Coded Values to Property File

If we look at our TestContext.java class, we have been using two hardcoded values:

base_Url = http://bookstore.toolsqa.com

user_Id = 9b5f49ab-eea9-45f4-9d66-bcf56a531b85

In the configuration.properties file, we will move these values in key-pair format.

Step 3: Create a Config File Reader

Page | 265
Firstly, right-click on the src/test/java and select New >> Package. In addition to that, name it
as dataProvider. Moreover, all the data-readers files will be kept here in this package.

Secondly, right-click on the above created package and select New >> Class. After that, name it as ConfigFileReader.

ConfigReader.java

package configs;

import java.io.BufferedReader;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.util.Properties;

public class ConfigReader {

private Properties properties;

private static ConfigReader configReader;

private ConfigReader() {

BufferedReader reader;

String propertyFilePath = "configs//Configuration.properties";

try {

reader = new BufferedReader(new FileReader(propertyFilePath));

properties = new Properties();

try {

properties.load(reader);

reader.close();

} catch (IOException e) {

e.printStackTrace();

} catch (FileNotFoundException e) {

e.printStackTrace();

throw new RuntimeException("Configuration.properties not found at " + propertyFilePath);

public static ConfigReader getInstance( ) {

if(configReader == null) {

Page | 266
configReader = new ConfigReader();

return configReader;

public String getBaseUrl() {

String baseUrl = properties.getProperty("base_Url");

if(baseUrl != null) return baseUrl;

else throw new RuntimeException("base_Url not specified in the Configuration.properties file.");

public String getUserID() {

String userId = properties.getProperty("user_Id");

if(userId != null) return userId;

else throw new RuntimeException("user_Id not specified in the Configuration.properties file.");

Code Explanation:

How to Load Property File

BufferedReader reader = new BufferedReader(new FileReader(propertyFilePath));

Properties properties = new Properties();

properties.load(reader);

• propertyFilePath: It would be a String variable containing the information of the config file path.

• new FileReader(propertyFilePath): Creates a new FileReader containing file-name, to be read from.

• new BufferedReader(new FileReader(propertyFilePath)): Reads the text from a character-input stream.


Moreover, it ensures efficient reading of the characters, arrays, and lines by buffering the characters.

• new Properties(): The Properties class represents a persistent set of properties. which can be saved to a
stream or loaded from it. Additionally, the key and the corresponding value in the property list is a string.

• properties.load(reader): It reads a property list of key and element pairs from the input character stream in a
simple line-oriented format.

If you have noticed the class ConfigReader.java, we have implemented it as a singleton class. The Singleton class’s
purpose is to control object creation, limiting the number of objects to only one. Additionally, there is only one
Singleton instance. Therefore, any instance fields of a Singleton would occur only once per class, similar to static
fields.

Why do we need Singleton class implementation?

Page | 267
Singleton pattern ensures the creation of only one instance of a class in the JVM. Moreover, it enables a global point
of access to the object. In our case, we have ConfigReader.java, which should be accessed globally. So it is better to
make the ConfigReader.java class as a singleton.

How to implement a Singleton Pattern?

The common concepts among several approaches to implement a Singleton pattern are:

• Private constructor

• Static field containing only it's an instance

• A public static method returning an instance of the class

public class ConfigReader {

// The Static member holds a single instance of the

// ConfigReader class

private static ConfigReader configReader;

// ConfigReader prevents any other class from instantiating

private ConfigReader() {

// Provides Global point of access

public static ConfigReader getInstance() {

if (configReader == null) {

configReader = new ConfigReader();

return configReader;

The ConfigReader.java class maintains a static reference to its instance. Additionally, it returns that reference from
the static getInstance() method.

ConfigReader.java implements a private constructor so clients cannot instantiate ConfigReader instances.

ConfigFileReader Method

public String getBaseUrl() {

String baseUrl = properties.getProperty("base_Url");

if(baseUrl != null) return baseUrl;

else throw new RuntimeException("base_Url not specified in the configuration.properties file.");

properties.getBaseUrl(): Properties object gives us a .getProperty method. Additionally, the input is Key of the
property sent as a parameter while the Value of the matched key is the output from the .properties file.

Page | 268
Moreover, if the properties file doesn't have the specified key, it returns the null. Hence, we have to put the null
check and, in case of null, throw an exception to stop the test with stack trace information.

For more details, you can visit the article on Singleton Pattern in Java.

Step 4: Use ConfigFileReader object in the TestContext file

After making the necessary changes for the BASE_URL and USER_ID inTextContext.java class:

private final String BASE_URL = "https://bookstore.toolsqa.com";

private EndPoints endPoints;

public TestContext() {

endPoints = new EndPoints(BASE_URL);

scenarioContext = new ScenarioContext();

scenarioContext.setContext(Context.USER_ID, USER_ID);

Consequently, the TextContext.java class transforms to:

package cucumber;

import apiEngine.EndPoints;

import configs.ConfigReader;

import enums.Context;

public class TestContext {

private EndPoints endPoints = new EndPoints(ConfigReader.getInstance().getBaseUrl());

private ScenarioContext scenarioContext;

public TestContext() {

scenarioContext = new ScenarioContext();

scenarioContext.setContext(Context.USER_ID, ConfigReader.getInstance().getUserID());

public EndPoints getEndPoints() {

return endPoints;

public ScenarioContext getScenarioContext() {

return scenarioContext;

Page | 269
Step 5: Run the Cucumber Test

Run the Tests as JUnit

We are all set now to run the updated Cucumber test. Firstly, Right -Click on ***TestRunner *class and Click Run
As >> JUnit Test. Cucumber runs the script in the same way as Selenium WebDriver. Finally, the result will display in
the JUnit tab of the console.

Run the Tests from Cucumber Feature

To run the tests as a Cucumber Feature, right-click on the End2End_Test.feature file. Select the Run As>>Cucumber
Feature.

Moreover, please try to implement the above changes in your framework, as explained above. Subsequently, our
updated project folder structure of the framework will look likewise:

The tests passed successfully with the changes we made to the Configuration Reader in our framework.

Page | 270
Rest Assured Examples
We have seen all the types of HTTP requests so far with respect to Rest Assured. Since these requests are distributed
in various tutorials, a collective reference can serve as a bookmark for our readers as they get their hands dirty with
rest assured. In this short post, we have combined rest assured examples with various HTTP requests with hands-on
code for each of them. This is also reflected in the index as below:

• Rest Assured examples with HTTP API Requests

o HTTP GET Request Implementation

o POST Request Implementation

o HTTP PUT Request Implementation

o HTTP DELETE Request Implementation

REST assured examples with HTTP API Requests

Rest Assured API supports functionality for various HTTP Requests like GET, POST, PUT, DELETE. Let us briefly discuss
each of these methods and also walkthrough implementation of each method in Rest Assured.

HTTP GET Request Implementation

The HTTP GET request is used widely in the API world. We can use this request to fetch/get a resource from a server
without sending any data with our requests. Since we are focusing on examples only in this post, you can refer to the
GET request post here.

Let us now implement the GET request using Rest Assured. The code for the same is shown below.

import io.restassured.RestAssured;

import io.restassured.http.Method;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

public class RestAssuredAPITest {

@Test

public void GetBooksDetails() {

// Specify the base URL to the RESTful web service

RestAssured.baseURI = "https://demoqa.com/BookStore/v1/Books";

// Get the RequestSpecification of the request to be sent to the server.

RequestSpecification httpRequest = RestAssured.given();

// specify the method type (GET) and the parameters if any.

//In this case the request does not take any parameters

Response response = httpRequest.request(Method.GET, "");

// Print the status and message body of the response received from the server

System.out.println("Status received => " + response.getStatusLine());

System.out.println("Response=>" + response.prettyPrint());
Page | 271
}

In the above code, we send a GET request to fetch the list of books and details of each book.

POST Request Implementation

Suppose we want to post/send some data on the server or create a resource on the server, then we go for an HTTP
POST request. For more information on the same, you can refer to Understanding HTTP POST Request Method
using Rest Assured for more details.

The following code implements the HTTP POST request using Rest Assured.

public void postRequestBooksAPI()

RestAssured.baseURI = "https://demoqa.com";

RequestSpecification request = RestAssured.given();

// JSONObject is a class that represents a Simple JSON.

// We can add Key - Value pairs using the put method

JSONObject requestParams = new JSONObject();

requestParams.put("userId", "TQ123");

requestParams.put("isbn", "9781449325862");

// Add a header stating the Request body is a JSON

request.header("Content-Type", "application/json"); // Add the Json to the body of the request

request.body(requestParams.toJSONString()); // Post the request and check the response

Response response = request.post("/BookStore/V1/Books");

System.out.println("The status received: " + response.statusLine());

Here we post a request to BookStore and get the response from the API.

HTTP PUT Request Implementation - Rest Assured Examples

The HTTP PUT request either update a resource or substitutes the representation of the target resource with the full
JSON request payload. For a detailed discussion on HTTP PUT requests, visit PUT Request using Rest Assured.

The code below makes a PUT request using Rest Assured.

import org.testng.Assert;

import org.testng.annotations.AfterTest;

import org.testng.annotations.BeforeTest;

import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.response.ResponseBody;
Page | 272
import io.restassured.specification.RequestSpecification;

public class UpdateBook {

String userId= "toolsqa_test";

String baseUrl="https://demoqa.com";

String token =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6InRlc3RpbmcxMjMiLCJwYXNzd29yZCI6IlBhc3N3b3JkQDEiL
CJpYXQiOjE2Mjg1NjQyMjF9.lW8JJvJF7jKebbqPiHOBGtCAus8D9Nv1BK6IoIIMJQ4";

String isbn ="9781449325865";

@Test

public void updateBook() {

RestAssured.baseURI = baseUrl;

RequestSpecification httpRequest = RestAssured.given().header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

//Calling the Delete API with request body

Response res = httpRequest.body("{ \"isbn\": \"" + isbn + "\", \"userId\": \"" + userId +
"\"}").put("/BookStore/v1/Book/9781449325862");

//Fetching the response code from the request and validating the same

System.out.println("The response code - " +res.getStatusCode());

Assert.assertEquals(res.getStatusCode(),200);

Here, we update the book record with the given ISBN value by setting a new ISBN value and also setting the userId
value.

HTTP DELETE Request Implementation

We can delete a resource from a server by making a DELETE request. We have a detailed description of the DELETE
request in the article, DELETE Request using Rest Assured.

The following Rest assured example demonstrates the working of HTTP DELETE Request.

package bookstore;

import org.testng.Assert;

import org.testng.annotations.AfterTest;

import org.testng.annotations.BeforeTest;

Page | 273
import org.testng.annotations.Test;

import io.restassured.RestAssured;

import io.restassured.response.Response;

import io.restassured.response.ResponseBody;

import io.restassured.specification.RequestSpecification;

public class DeleteBook {

String userId= "de5d75d1-59b4-487e-b632-f18bc0665c0d";

String baseUrl="https://demoqa.com";

String token =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyTmFtZSI6InRlc3RpbmcxMjMiLCJwYXNzd29yZCI6IlBhc3N3b3JkQDEiL
CJpYXQiOjE2Mjg1NjQyMjF9.lW8JJvJF7jKebbqPiHOBGtCAus8D9Nv1BK6IoIIMJQ4";

String isbn ="9781449337711";

@Test

public void deleteBook() {

RestAssured.baseURI = baseUrl;

RequestSpecification httpRequest = RestAssured.given().header("Authorization", "Bearer " + token)

.header("Content-Type", "application/json");

//Calling the Delete API with request body

Response res = httpRequest.body("{ \"isbn\": \"" + isbn + "\", \"userId\": \"" + userId +
"\"}").delete("/BookStore/v1/Book");

//Fetching the response code from the request and validating the same

System.out.println("The response code is - " +res.getStatusCode());

Assert.assertEquals(res.getStatusCode(),204);

The above code is for the HTTP DELETE request. Here we pass the ISBN and the userId for which the resource is to be
deleted. The response obtained confirms the deletion (or if not).

END OF THİS BOOK

Page | 274

You might also like