Hi all, This is a 2 parts blog about Restassured API - here we are trying to understand more about Payloads or HTTP Request body with data.
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.
REST Assured treats our REST application as a Black box during testing. All REST Assured tests send a network request to our application, get a response back, and compare it against a predetermined result.
The HTTP request message always starts with HTTP method name such as GET, POST, PUT, DELETE, HEAD, etc
It is the responsibility of the consumer to prepare and send HTTP request message with the appropriate HTTP method name depending on operation:
-The GET method is used to perform the READ operation.
-The POST method is used to perform INSERT operation.
-The PUT method is used to perform UPDATE operation.
-The DELETE method is used to perform the DELETE operation.
Th application under test (AUT) can be written in Java or anyother programming language, it is irrelevant to REST Assured. REST Assured bases its tests only on JSON and HTTP, which are language-independent technologies. We can use REST Assured to write tests for applications written with Python, Ruby, .NET etc.
REST Assured supports mapping Java objects to and from JSON and XML. For Mapping
Java objects to or from JSON you need to have either Jackson, Jackson2, Gson or Johnzon in the classpath
Java objects to or from XML you need Jakarta EE or JAXB.
This blog primarily talks about JSON payloads
A client that generates an OPTIONS request containing a payload body MUST send a valid Content-Type header field describing the representation media type.
What is Payload in REST API?
The payload of an API is the data you are interested in transporting to the server when you make an API request.
In simple words, the payload means body in the HTTP request and response message. It's optional and depends on the HTTP method name i.e.,HTTP Request Message
API Payload Formats
Basically, you’ll find three payload formats:
1. Request payload format : This request must have two parameters and a sub-element
Interface Type,
Method name ,
Parameters
Example:
{
"interfaceType": "Manual",
"methodName": "",
"parameters": {
}
}
2. OK response payload format : This features one parameter and one sub-element
Response type,
Data(It may be zero or more parameters)
Example:
{
"responseType": "OK",
"data": {
"someName1": "value",
"someName2": "value",
..........
}
}
3. FAILED response payload format - This also contains one parameter and one subelement:
Response type
Messages( May feature an array of zero or multiple error messages)
Example:
{
"responseType": "FAILED", "messages":
[
{ "message": "" },
{ "message": "" },
{ "message": "" }
]
}
It is the responsibility of the consumer to prepare and send HTTP request message with the appropriate HTTP method name depending on operation:
-In the case of GET HTTP method, the HTTP request message without a body.
-In the case of the POST HTTP method, the HTTP request message with body
The 'Content-Type' header name in the HTTP request message is used to represent payload format in the HTTP request message. For example: JSON, XML etc.
JSON payload format example:
{
"cid": 1,
"cname": "numpyninja",
"email": "numpyninja@gmail.com"
}
XML payload format example:
<company>
<cid>1</cid>
<cname>numpyninja</cname>
<email>numpyninja@gmail.com</email>
</company>
Http Response Message
The 'Accept' header name in an HTTP request message is used to represent the expected payload format in an HTTP response message. For example:JSON, XML, plain text, HTML etc.
It is the responsibility of the business component (developed by the service provider) to prepare and send HTTP response message
HTTP/1.1 200 OK
Content-Type: application/xml
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Mon, 10 Nov 2019 09:45:34 GMT
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer>
<cid>1</cid>
<cname>numpyninja</cname>
<email>numpyninja@gmail.com</email>
</company>
The HTTP response message contains any one of the HTTP status code ranges between 100 and 599:
Informational : 1xx
Successful : 2xx
Re-directional : 3xx
Client side error : 4xx
Server side error : 5xx
From the above Response message, the payload means body in HTTP response message is optional and depends on http status code i.e.,
-In the case of the 204 status code, the HTTP response message without a body
-In the case of the 200 status code, the HTTP response message with body
The 'Content-Type' header name in the HTTP response message is used to represent payload format in an HTTP response message.
Whether it will be serialized to JSON or XML that depends upon what we pass as Content-Type.
Content-Type = application/json :Rest Assured will serialize the Object to JSON.
Rest Assured will look for which JSON parser is available in class path. First it looks for Jackson. If Jackson is not found it looks for GSON. If both are not found then an exception IllegalArgumentException stating “Cannot serialize because no JSON or XML serializer found in classpath.” will be thrown.
Content-Type = “application/xml” : Rest Assured will serialize Object in to XML
Rest Assured will look for JAXB library in class path of project. If it is not found then an exception IllegalArgumentException stating “Cannot serialize because no JSON or XML serializer found in classpath.” will be thrown.
Content-Type = " null" or empty : Rest Assured will first try to parse in JSON using Jackson library. If Jackson is not found, it will look for GSON. If both are not found, it will parse in to XML using JAXB. If none found, exception will be thrown.
Note :- This works for the POST and PUT methods only.
Serialization and Deserialization
A Plain Old Java Object POJO is used to create JSON payload and convert JSON response payload to Java objects.
Converting a POJO object to a JSON object is Serialization
Converting a JSON object to a POJO object is called deserialization.
These conversions can be done with help of Java libraries like Jackson, Gson etc. We don’t need to implement the required interfaces for POJO classes. A serialized object can be stored in files, external sources, databases etc and can also be transferred over networks.
Serialization and Deserialization are not specific to RestAssured. It is related to programming language i.e. Java here.
JSON Objects
JSONObject is object instance of JSONObject class that is defined in the org.json package. Its from the googlecode -json -Simple library
Add the following dependency in POM.xml file
<!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
The object value is an unordered group of name-value pairs called JSONObjects {} or
Ordered group of name-value pairs called JSONArrays[].
A JSON Object is a key-value pair and can be easily created using a Java Map. A Map in Java also represents a collection of key-value pairs.Keys are unique Strings that cannot be null
Values can be anything from a Boolean, Number, String, JSONArray or even a JSONObject.NULL object
A JSONObject can be represented by a String enclosed within curly braces{} with keys and values separated by a colon, and pairs separated by a comma
It has several constructors with which to construct a JSONObject
Having understood what Papyload is , we can now explore different methods to add payload to a HTTP Request.
I have explored the " petstore" API using Swagger UI in the following example
Lets consider the POST request with a payload as shown below:
(body)
1.Pet object that needs to be added to the store
Here the request body has a JSON object and expects the response body to contain JSON object
2. Lets execute this request
3. The following is the request sent Note the " Content_type: application/json"
4. The response looks as follows
Status code 200 ------>Request completed successfully
Note the " Content_type: application/json"
After creating the Project with the folder structure looks like this
The constants.java class
Payload as a JSONObject using json-simple library
package TestcasesPetstore;
import static io.restassured.RestAssured.given;
import static org.junit.Assert.assertEquals;
import static org.hamcrest.Matchers.*;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.testng.annotations.Test;
import com.qa.petstore.constants;
import io.restassured.matcher.ResponseAwareMatcher;
import io.restassured.module.jsv.JsonSchemaValidator;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.response.ValidatableResponseOptions;
// json body payloads {} --> maptype of data..can use hashmap or json object,
//[] -->array type of data.....use arraylist
public class payloadexample_post {
@Test (priority=1)//Payload- JSONobject
public void Postrequestusingjsonobjectpayload() {
System.out.println( "TEST 1 : Post Request : Payload- JSONobject ============= ");
JSONObject requestbody = new JSONObject();
// Add a header stating the Request body is a JSON
requestbody.put("id", "7794589");
requestbody.put("status", "available");
requestbody.put("name", "Caesar");
// adding category - id and name
JSONObject categoryobj = new JSONObject();
categoryobj.put("id", "5100");
categoryobj.put("name", "Cats");
// JSONArray categoryArr = new JSONArray();
// categoryArr.add(categoryobj);
requestbody.put("category", categoryobj);
// photourls saved as array
JSONArray photoUrls = new JSONArray();
requestbody.put("photoUrls", photoUrls);// photourlsarray addedto jsonobj
// adding tags - id and name saved to array
JSONObject tagObj = new JSONObject();
tagObj.put("id", "4500");
tagObj.put("name", "pet");
JSONArray tagArr = new JSONArray();
tagArr.add(tagObj);
requestbody.put("tags", tagArr);// tags added to jsonobj
System.out.println(requestbody.toJSONString());
Response response = given()
.acept("application/json")
.contentType("application/json") // request.header("Content-Type","application/json")
.body(requestbody.toJSONString())
.log().all()
.when().post(constants.Base_URL +"pet")(// https://petstore.swagger.io/v2/pet)
.then()
// .assertThat().statusCode(201)
.extract().response();
JsonPath jpath = response.jsonPath();// to readable format
System.out.println(response.body().asString());
String jsonasString = response.asPrettyString();
System.out.println(jsonasString);
// validating Status Code
int statusCode = response.getStatusCode();
System.out.println(" Status Code for Post request is :" + statusCode);
assertEquals(200, statusCode);
System.out.println( "TEST 1 : Post Request : Payload- Jsonobject ends ================= ");
}
The console output looks like this with status code 200
2. In the next test, we created a payload using Hashmap
//Payload - HASHMAP
@Test (priority=2)
public void Postrequestusinghashmappayload() {
// -----------create payload for request body in hashmap format----------
System.out.println( "TEST 2 : Post Request : Payload - HASHMAP" + "==============");
HashMap<String, Object> requestMap = new HashMap<String, Object>();
requestMap.put("id", 79);
requestMap.put("status", "available");
requestMap.put("name", "Caesar");
//category key has values in {..} which indicate a map
//create category map and add to category{} of requestMap
HashMap<String, Object> categoryMap = new HashMap<String, Object>();
categoryMap.put("id", 5000);
categoryMap.put("name", "Fish");
requestMap.put("category", categoryMap);
//photourl has values in [..] which indicate an array.....so an arraylist was created
// create Array for photourls[] and add it to requestMap
ArrayList<String> purlarray = new ArrayList<String>();
purlarray.add("photourl1");
purlarray.add("photourl2");
requestMap.put("photoursl", purlarray);
/* ags has values in [..] which indicate an array.and inside this array {id and names}which indicate a map.so an arraylist <map> was created create Array for tags[] and add it to requestMap */
ArrayList<Map<String, Object>> tagsarray = new ArrayList<Map<String, Object>>();
// tagsarray[] contains key-value pairs - create a map for that
HashMap<String, Object> tagsMap = new HashMap<String, Object>();
tagsMap.put("id", 21);
tagsMap.put("name", "leo");
tagsMap.put("id", 22);
tagsMap.put("name", "Rio");
tagsMap.put("id", 23);
tagsMap.put("name", "rodeo");
// add map to array
tagsarray.add(tagsMap);
// add array to requestMap
requestMap.put("tags", tagsarray);
//------------------add payload hashmap to Postrequest ------------
Response response = given().accept("application/json").contentType("application/json")
//request.header("Content-Type","application/json")
.body(requestMap)
.log().all()
.when().post(constants.Base_URL + "pet")
// https://petstore.swagger.io/v2/pet
.then().assertThat()
.statusCode(200) .body(JsonSchemaValidator.matchesJsonSchemaInClasspath("jsonschemaforpetstore.json")).extract()
.response();
}
In the next part of the blog... we will consider more payload examples. Hope this blog was useful.