Rest Assured – How to test JSON Request using Jackson API

HOME

This tutorial focuses on the testing of a REST API (with JSON payload). We will use Jackson API to serialize the request.

It is suggested to go through these tutorials to understand about creating a JSON Object Payload using POJO (Plain Old Java Object).

How to create JSON Object Payload using POJO – Jackson API

How to create JSON Array Payload using POJO – Jackson API

How to create Nested JSON Object using POJO – Jackson API

To start with, we need to add Jackson Maven Dependency to the POM. Always add the latest version of Jackson dependency to your project.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
</dependency>

This dependency will also transitively add the following libraries to the classpath:

  1. jackson-annotations
  2. jackson-core

In the below example, let us assume that we need to create a new Employee (POST Request) .To start with, we need to create POJO class of the JSON payload (EmployeeDetails). This POJO class should contain the data members corresponding to the JSON nodes and their corresponding getter and setter methods.

public class EmployeeDetails {

	// private variables or data members of pojo class
	private String name;
	private double salary;
	private int age;

    // Getter and Setters
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

Now that we have our POJO class we can start writing some REST Assured Serialization tests!

Let’s start with REST Assured Serialization with JSON. I want to send a POST request to my EmployeeDetails API that will add a new Employee to the database. I will send a POJO of the employee in the request body. This is what the code looks like in the test class:

	@Test
	public void createEmployee() {

		// Create an object of POJO class
		EmployeeDetails emp = new EmployeeDetails();
		emp.setName("Vibha");
		emp.setSalary(75000);
		emp.setAge(30);

		// Converting a Java class object to a JSON payload as string
		ObjectMapper mapper = new ObjectMapper();
		String employeePrettyJson = null;
		try {
			employeePrettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(emp);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		System.out.println("Request");
		System.out.println(employeePrettyJson);
		System.out.println("=========================================");
		System.out.println("Response");

		// GIVEN
		given().baseUri("http://dummy.restapiexample.com/api").contentType(ContentType.JSON).body(emp)

				// WHEN
				.when().post("/v1/create")

				// THEN
				.then().assertThat().statusCode(200).body("data.name", equalTo("Vibha"))
				.body("message", equalTo("Successfully! Record has been added.")).log().body();

	}
}

If you want to see the structure of Request, then add the below in the test code.

ObjectMapper mapper = new ObjectMapper();
String employeePrettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(emp);
System.out.println(employeePrettyJson);

REST Assured Serialization with Jackson handled all the serialization work for us. Great! See this has become so simple with the help of Jackson API.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

How to create JSON Array Payload using POJO – Jackson API

HOME

In the previous tutorial, I have explained the creation of JSON Object using POJO. In this tutorial, will create a JSON Array Payload using POJO.

To know about POJO, please refer to this tutorial.

You can refer these tutorials to understand various ways of using Jackson API

Serialization – How to create JSON Payload from Java Object – Jackson API

How to create JSON Array Payload using POJO – Jackson API

How to create Nested JSON Object using POJO – Jackson API

Serialization – How to convert Map to JSON string using Jackson API

JSON Array is a collection of JSON Objects. In the below example, will create a list of employees.

The sample JSON Array structure looks like the image as shown below:-

{
  "firstName" : "Vibha",
  "lastName" : "Singh",
  "age" : 30,
  "salary" : 75000.0,
  "designation" : "Manager",
  "contactNumber" : "+919999988822",
  "emailId" : "abc@test.com"
  
  "firstName" : "Neha",
  "lastName" : "Verma",
  "age" : 25,
  "salary" : 60000.0,
  "designation" : "Lead",
  "contactNumber" : "+914442266221",
  "emailId" : "xyz@test.com"
  
  "firstName" : "Rajesh",
  "lastName" : "Gupta",
  "age" : 20,
  "salary" : 40000.0,
  "designation" : "Intern",
  "contactNumber" : "+919933384422",
  "emailId" : "pqr@test.com"
}

We need to create an Employee class that contains private data members and corresponding getter and setter methods of these data members.

Below is an Employee Class with private data members, as well as the corresponding getter and setter methods of these data members. Every IDE provides a shortcut to create these getter and setter methods.

public class Employee {

	// private variables or data members of POJO class
	private String firstName;
	private String lastName;
	private int age;
	private double salary;
	private String designation;
	private String contactNumber;
	private String emailId;

	// Getter and setter methods
	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}

	public String getContactNumber() {
		return contactNumber;
	}

	public void setContactNumber(String contactNumber) {
		this.contactNumber = contactNumber;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

}

Serialization – Serialization is a process where you convert an Instance of a Class (Object of a class) into a Byte Stream. Here, we are converting Employee class object to JSON Array representation or Object.

Deserialization – It is the reverse of serializing. In this process, we will read the Serialized byte stream from the file and convert it back into the Class instance representation. Here, we are converting a JSON Array to an Employee class object.

We are using Jackson API for Serialization and Deserialization. So, add the Jackson dependency to the project.

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
</dependency>

Below is the class where we will assign values to the data members by using getter methods (Serialization).

public class EmployeeArrayTest {

	@Test
	public void createEmployeeArray() {

		Employee emp1 = new Employee();
		emp1.setFirstName("Vibha");
		emp1.setLastName("Singh");
		emp1.setAge(30);
		emp1.setSalary(75000);
		emp1.setDesignation("Manager");
		emp1.setContactNumber("+919999988822");
		emp1.setEmailId("abc@test.com");

		Employee emp2 = new Employee();
		emp2.setFirstName("Neha");
		emp2.setLastName("Verms");
		emp2.setAge(35);
		emp2.setSalary(60000);
		emp2.setDesignation("Lead");
		emp2.setContactNumber("+914442266221");
		emp2.setEmailId("xyz@test.com");

		Employee emp3 = new Employee();
		emp3.setFirstName("Rajesh");
		emp3.setLastName("Gupta");
		emp3.setAge(20);
		emp3.setSalary(40000);
		emp3.setDesignation("Intern");
		emp3.setContactNumber("+919933384422");
		emp3.setEmailId("pqr@test.com");

		// Creating a List of Employees
		List<Employee> employeeList = new ArrayList<Employee>();
		employeeList.add(emp1);
		employeeList.add(emp2);
		employeeList.add(emp3);

		// Converting a Java class object to a JSON Array Payload as string
		ObjectMapper mapper = new ObjectMapper();
		try {
			String allEmployeeJson = mapper.writeValueAsString(employeeList);
			String employeeListPrettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(employeeList);
			System.out.println(allEmployeeJson);
			System.out.println(employeeListPrettyJson);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
	}

ObjectMapper is imported from:-

import com.fasterxml.jackson.databind.ObjectMapper;

In the below example, we are deserializing the JSON Array Payload to Java objects.

    @Test
	public void getEmployeeArray() {

		Employee emp1 = new Employee();
		emp1.setFirstName("Vibha");
		emp1.setLastName("Singh");
		emp1.setAge(30);
		emp1.setSalary(75000);
		emp1.setDesignation("Manager");
		emp1.setContactNumber("+919999988822");
		emp1.setEmailId("abc@test.com");

		Employee emp2 = new Employee();
		emp2.setFirstName("Neha");
		emp2.setLastName("Verms");
		emp2.setAge(35);
		emp2.setSalary(60000);
		emp2.setDesignation("Lead");
		emp2.setContactNumber("+914442266221");
		emp2.setEmailId("xyz@test.com");

		Employee emp3 = new Employee();
		emp3.setFirstName("Rajesh");
		emp3.setLastName("Gupta");
		emp3.setAge(20);
		emp3.setSalary(40000);
		emp3.setDesignation("Intern");
		emp3.setContactNumber("+919933384422");
		emp3.setEmailId("pqr@test.com");

		// Creating a List of Employees
		List<Employee> employeeList = new ArrayList<Employee>();
		employeeList.add(emp1);
		employeeList.add(emp2);
		employeeList.add(emp3);

		// Converting a Java class object to a JSON Array Payload as string

		ObjectMapper mapper = new ObjectMapper();
		String allEmployeeJson = null;

		try {
			allEmployeeJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(employeeList);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}

		List<Employee> allEmployeeDetails = null;
		try {
			allEmployeeDetails = mapper.readValue(allEmployeeJson, new TypeReference<List<Employee>>() {
			});
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}

		for (Employee emp : allEmployeeDetails) {

			System.out.println("===================================");

			System.out.println("First Name of employee : " + emp.getFirstName());
			System.out.println("Last Name of employee : " + emp.getLastName());
			System.out.println("Age of employee : " + emp.getAge());
			System.out.println("Salary of employee : " + emp.getSalary());
			System.out.println("Designation of employee : " + emp.getDesignation());
			System.out.println("Contact Number of employee : " + emp.getContactNumber());
			System.out.println("EmailId of employee : " + emp.getEmailId());
		}
	}

If you want to read the data from a file placed on Desktop, below is the sample code for the same.

@Test
	public void readArrayJsonFromFile() throws IOException {

		ObjectMapper mapper = new ObjectMapper();

		// Converting Employee json string to Employee class object
		List<Employee> allEmployeeDetails = null;
		try {
			allEmployeeDetails = mapper.readValue(new File(
					"C:\\Users\\Vibha\\Desktop\\EmployeeList.json"),
					new TypeReference<List<Employee>>() {
					});
		} catch (StreamReadException e) {
			e.printStackTrace();
		} catch (DatabindException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}


		for (Employee emp : allEmployeeDetails) {

			System.out.println("######################################");

			System.out.println("First Name of employee : " + emp.getFirstName());
			System.out.println("Last Name of employee : " + emp.getLastName());
			System.out.println("Age of employee : " + emp.getAge());
			System.out.println("Salary of employee : " + emp.getSalary());
			System.out.println("Designation of employee : " + emp.getDesignation());
			System.out.println("Contact Number of employee : " + emp.getContactNumber());
			System.out.println("EmailId of employee : " + emp.getEmailId());
		}
	}

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Serialization – How to create JSON Payload from Java Object – Jackson API

HOME

In this tutorial, I will explain the creation of JSON Object Payload with the help of POJO (Plain Old Java Object).

What is POJO?

POJO stands for Plain Old Java Object. It is a very simple object and it has no bound or we can say that it has no restrictions other than the Java language specification. Also, it does not require any classpath.

A big advantage of POJO is it increases the readability and reusability of our project code and developers find it easy when understanding the code. Also, POJO is easy to write and anyone can understand them easily.

Now let’s deep dive into some technical terms about the POJO. Below are a few points about the POJO are:

  1. A POJO should not have to extend prespecified classes.
  2. Secondly, a POJO should not have implemented any prespecified interface.
  3. Lastly, POJO should not contain prespecified annotations

A POJO class can follow some rules for better usability. These rules are:-

  1. Each variable should be declared as private just to restrict direct access.
  2. Each variable which needs to be accessed outside class may have a getter or a setter or both methods. If value of a field is stored after some calculations then we must not have any setter method for that.
  3. It Should have a default public constructor.
  4. Can override toString(), hashcode and equals() methods.

POJO classes are extensively used for creating JSON and XML payloads for API.

In the below example, let me create a simple JSON with some nodes which is actually a 1:1 mapping i.e. each key has a single value, and the type of values is mixed.

{
  "firstName" : "Vibha",
  "lastName" : "Singh",
  "age" : 30,
  "salary" : 75000.0,
  "designation" : "Manager",
  "contactNumber" : "+91999996712",
  "emailId" : "abc123@test.com"
}

Let us create variables in the POJO class now for the above JSON. Now, a class name Employee will be created with the private data members as mentioned in the above JSON. Since we have created all variables as private, then there should be a way to manipulate or retrieve these data. So we create the corresponding getter and setter methods for these data members.

It is very tedious to create getter and setter methods for all the data members for big JSON strings.  Every IDE gives you a shortcut to generate getter and setter methods.  Here, I am using Eclipse and creating these getter and setter methods.

Select all the data members and Right-click on the page. Then select Source and then select Generate Getter and Setter methods.

This opens a new screen as shown below.

You can select the data member for which you want to create the getter and setter method. I want to create the getter and setter methods for all the data members, so click on Select All and then click on the Generate Button. This will generate the getter and setter methods for all the data members.

Below is the sample code of the Employee table, which contains the data members needed for Employee JSON and their corresponding getter and setter methods.

public class Employee {

	// private variables or data members of POJO class
	private String firstName;
	private String lastName;
	private int age;
	private double salary;
	private String designation;
	private String contactNumber;
	private String emailId;

	// Getter and setter methods
	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public String getDesignation() {
		return designation;
	}

	public void setDesignation(String designation) {
		this.designation = designation;
	}
	
	public String getContactNumber() {
		return contactNumber;
	}

	public void setContactNumber(String contactNumber) {
		this.contactNumber = contactNumber;
	}

	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

}

Using the above POJO class, you can create any number of custom Employee objects and each object can be converted into a JSON Object and Each JSON object can be parsed into Employee POJO.

We will create a JSON object from POJO and vice versa now, which is generally called serialization and deserialization using Jackson APIs.

Serialization – Serialization is a process where you convert an Instance of a Class (Object of a class) into a Byte Stream. Here, we are converting Employee class object to JSON representation or Object

Deserialization – It is the reverse of serializing. In this process, we will read the Serialized byte stream from the file and convert it back into the Class instance representation. Here, we are converting a JSON Object to an Employee class object.

We are using Jackson API for Serialization and Deserialization. So, add the Jackson dependency to the project.

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
</dependency>

What is ObjectMapper ?

ObjectMapper provides functionality for reading and writing JSON, either to and from basic POJOs (Plain Old Java Objects), or to and from a general-purpose JSON Tree Model (JsonNode), as well as related functionality for performing conversions. It is also highly customizable to work both with different styles of JSON content and to support more advanced object concepts such as polymorphism and object identity.

Now, let us create a Test Class to show Serialization.

public class EmployeeTest {

	@Test
	public void serializationTest()  {

		Employee employee = new Employee();
		employee.setFirstName("Vibha");
		employee.setLastName("Singh");
		employee.setAge(30);
		employee.setSalary(75000);
		employee.setDesignation("Manager");

		// Converting a Java class object to a JSON payload as string
		ObjectMapper mapper = new ObjectMapper();
		String employeeJson = mapper.writeValueAsString(employee);
		String employeePrettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee);
		System.out.println(employeeJson);
		System.out.println(employeePrettyJson);
   }
}try {
			String employeeJson = mapper.writeValueAsString(employee);
			System.out.println(employeeJson);
			String employeePrettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee);
			System.out.println(employeePrettyJson);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}	
	}

Here, ObjectMapper from fasterxml.jackson.databind is used for Serialization.

writeValueAsString() is a method that can be used to serialize any Java value as a String.

writerWithDefaultPrettyPrinter() is used to pretty-print the JSON output. It is a Factory method for constructing ObjectWriter that will serialize objects using the default pretty printer for indentation.

I hope this has helped to clear your doubts regarding POJO and how to create JSON Object using POJO.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Integration of Serenity with Rest Assured

HOME

In this tutorial, I will explain the Integration of Serenity BDD with Rest Assured for the testing of RestFul API.

What is Serenity BDD?

Serenity BDD is an open-source library that aims to make the idea of living documentation a reality.

What is Rest Assured?

Rest Assured is one of the most powerful libraries for testing RESTful API using Java language. 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. The rest-Assured library also provides the ability to validate the HTTP Responses received from the server. 

Pre-Requisite

  1. Java 11 installed
  2. Maven installed
  3. Eclipse or IntelliJ installed

This framework consists of:

  1. Java 11
  2. Maven – 3.8.1
  3. Serenity – 3.2.5
  4. Serenity Rest Assured – 3.2.5
  5. Rest Assured – 5.1.1
  6. JUnit – 4.13.2
  7. Maven Surefire Plugin – 3.0.0-M5
  8. Maven Failsafe Plugin – 3.0.0-M5
  9. Maven Compiler Plugin – 3.8.1

Implementation Steps

  1. Update Properties section in Maven pom.xml
  2. Add repositories and pluginRepository to Maven pom.xml
  3. Add Serenity, Serenity Rest Assured, and JUnit4 dependencies to POM.xml
  4. Update Build Section of pom.xml
  5. Create the Test Code under src/java/test
  6. Create serenity.properties file in the root of the project
  7. Run the tests through the command line which generates Serenity Reports.

Project Structure

Step 1 – Update the Properties section in Maven pom.xml

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <serenity.version>3.2.5</serenity.version>
    <serenity.maven.version>3.2.5</serenity.maven.version>
    <junit.version>4.13.2</junit.version>
    <rest.assured.version>5.1.1</rest.assured.version>
    <json.version>20210307</json.version>
    <maven.surefire.plugin.version>3.0.0-M5</maven.surefire.plugin.version>
    <maven.failsafe.plugin.version>3.0.0-M5</maven.failsafe.plugin.version>
    <maven.compiler.plugin.version>3.8.1</maven.compiler.plugin.version>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

Step 2 – Add repositories and pluginRepository to Maven pom.xml

  <repositories>
        <repository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>bintray</name>
            <url>https://jcenter.bintray.com</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>bintray-plugins</name>
            <url>https://jcenter.bintray.com</url>
        </pluginRepository>
    </pluginRepositories>

Step 3 – Add Serenity, Serenity Cucumber, Serenity Rest Assured, Rest Assured, and JUnit dependencies to POM.xml

<dependencies>
   <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-core</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-junit</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
      
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-screenplay-rest</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-rest-assured</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>${rest.assured.version}</version>
            <scope>test</scope>
        </dependency>
         
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>  
  
       <dependency>
           <groupId>org.json</groupId>
           <artifactId>json</artifactId>
           <version>${json.version}</version>
        </dependency> 
        
    </dependencies>

Step 4 – Update the Build Section of pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven.failsafe.plugin.version}</version>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                        <include>**/*.Test</include>
                    </includes>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
           <plugin>
               <groupId>net.serenity-bdd.maven.plugins</groupId>
               <artifactId>serenity-maven-plugin</artifactId>
               <version>${serenity.version}</version>
               <dependencies> 
                  <dependency>
                       <groupId>net.serenity-bdd</groupId>
                       <artifactId>serenity-single-page-report</artifactId>
                       <version>${serenity.version}</version>
                  </dependency>                
               </dependencies>
               <configuration>
                   <tags>${tags}</tags>
                   <reports>single-page-html</reports> 
               </configuration>
               <executions>
                  <execution>
                      <id>serenity-reports</id>
                      <phase>post-integration-test</phase>
                      <goals>
                          <goal>aggregate</goal>
                      </goals>
                   </execution>
               </executions>
           </plugin>
        </plugins>
    </build>

Step 5 – Create the Test Code in src/java/test directory

There are 2 ways to create the same test. One approach is to have a Definition file that contains all the test code as shown below.

    
    private static final String URL = "http://dummy.restapiexample.com/api/v1";
	public Response response;

     @Test
	public void verifyValidUser() {

		response = SerenityRest.given().contentType("application/json").header("Content-Type", "application/json").when().get(URL + "/employee/" + id);

		SerenityRest.restAssuredThat(response -> response.statusCode(200)
                    .body("data.id", equalTo(1))
				    .body("data.employee_salary", equalTo(320800))
                    .body("data.employee_name", equalTo("Tiger Nixon"))
                    .body("data.employee_age", equalTo(61)).and()
				    .body("message", equalTo("Successfully! Record has been fetched.")));

	}

	@Test
	public void verifycreateUser() {
        JSONObject data = new JSONObject();

		data.put("employee_name", "Shawn Test");
		data.put("profile_image", "test.png");
		data.put("employee_age", 30);
		data.put("employee_salary", 11111);

		response = SerenityRest.given().contentType("application/json").header("Content-Type", "application/json")
				.body(data.toString()).when().post(URL + "/create");
		
      SerenityRest.restAssuredThat(response -> response.statusCode(200)
				    .body("data.employee_salary", equalTo(11111))
                    .body("data.employee_name", equalTo("Shawn Test"))
                    .body("data.employee_age", equalTo(30)).and()
				    .body("message", equalTo("Successfully! Record has been added.")));

	}

Another approach is that all tests are split into reusable blocks called “steps”. The main principle of the BDD approach is that we are trying to keep complexity to a high-level human-readable level. First of all, let’s create a separate package to keep our steps. It is always better to keep them separate as it shows which classes contain reusable components. It is better to make steps smaller. So let’s make separate reusable steps from our tests:

import static org.hamcrest.Matchers.equalTo;
import org.json.JSONObject;
import io.restassured.response.Response;
import net.serenitybdd.rest.SerenityRest;
import net.thucydides.core.annotations.Step;

public class EmployeeSteps {

	private static final String URL = "http://dummy.restapiexample.com/api/v1";
	public Response response;

	@Step("Search user by id {0}")
	public void sendUser(int id) {
		response = SerenityRest.given().contentType("application/json").header("Content-Type", "application/json")
				.when().get(URL + "/employee/" + id);

	}

	@Step("Create a new user")
	public void createUser() {

		JSONObject data = new JSONObject();

		data.put("employee_name", "Shawn Test");
		data.put("profile_image", "test.png");
		data.put("employee_age", 30);
		data.put("employee_salary", 11111);

		response = SerenityRest.given().contentType("application/json").header("Content-Type", "application/json")
				.body(data.toString()).when().post(URL + "/create");

	}

	@Step("Verify the status code {0}")
	public void verifyStatusCode(int expectedStatusCode) {
		SerenityRest.restAssuredThat(response -> response.statusCode(expectedStatusCode));
	}

	@Step("Verify the user id {0}")
	public void verifyId(int expectedId) {
		SerenityRest.restAssuredThat(response -> response.body("data.id", equalTo(expectedId)));
	}

	@Step("Verify the user name {0}")
	public void verifyName(String expectedName) {

		SerenityRest.restAssuredThat(response -> response.body("data.employee_name", equalTo(expectedName)));
	}

	@Step("Verify the user salary {0}")
	public void verifySalary(int expectedSalary) {
		SerenityRest.restAssuredThat(response -> response.body("data.employee_salary", equalTo(expectedSalary)));
	}

	@Step("Verify the user age {0}")
	public void verifyAge(int expectedAge) {
		SerenityRest.restAssuredThat(response -> response.body("data.employee_age", equalTo(expectedAge)));
	}

	@Step("Verify the message {0}")
	public void verifyMessage(String expectedMessage) {
		SerenityRest.restAssuredThat(response -> response.body("message", equalTo(expectedMessage)));
	}

}


Now our steps are ready. Let’s refactor the main class with our tests:

import org.example.SerenityWithRestAssuredDemo.steps.EmployeeSteps;
import org.junit.Test;
import org.junit.runner.RunWith;

import net.serenitybdd.junit.runners.SerenityRunner;
import net.thucydides.core.annotations.Steps;
import net.thucydides.core.annotations.Title;

@RunWith(SerenityRunner.class)
public class EmployeesTest {

	@Steps
	EmployeeSteps employeeSteps;

	@Test
	@Title("Get User")
	public void verifyValidUser() {
		employeeSteps.sendUser(1);
		employeeSteps.verifyStatusCode(200);
		employeeSteps.verifyId(1);
		employeeSteps.verifyName("Tiger Nixon");
		employeeSteps.verifyAge(61);
		employeeSteps.verifySalary(320800);
		employeeSteps.verifyMessage("Successfully! Record has been fetched.");

	}

	@Test
	@Title("Create User")
	public void createValidUser() {

		employeeSteps.createUser();
		employeeSteps.verifyStatusCode(200);
		employeeSteps.verifyName("Shawn Test");
		employeeSteps.verifyAge(30);
		employeeSteps.verifySalary(11111);
		employeeSteps.verifyMessage("Successfully! Record has been added.");

	}

}

One more important thing we added is the “@RunWith(SerenityRunner.class)” annotation on top of the class. As we have now organized our structure to meet some basic Serenity principles, we are ready to run the test using Serenity. This time (after we added the mentioned annotation) these tests will be run using the “SerenityRunner”. For that we can use exactly the same command to run our tests:

mvn clean verify

In the console, you should find printed messages for tests to start. At the same time under the target directory you can find the HTML-generated report we were talking about before:

You can open the report in any browser:

If you click on any test you should see a detailed description of the test steps:

One of the most important features of the Serenity and REST Assured integration is that by using detailed reporting, you can easily validate all requests and response details even if you are not adding any logs inside tests. Like the example above, for each executed REST request you can click the button “REST Query” and get a detailed request and response description:

There is another very useful Serenity Report – Serenity Symmary.html

As you can see, Serenity and REST Assured provide you with a wonderful combination. REST Assured keeps API testing clean and easy to maintain, while Serenity gives you outstanding test reporting and flexibility in running and grouping your tests inside a test suite.

Complete Source Code:
Refer to GitHub for source code.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Integration of REST Assured with TestNG

HOME

As we know, REST Assured is a Java DSL for simplifying testing of REST based services built on top of HTTP Builder. In this tutorial, I’ll create a Test Framework for the testing of REST API using REST Assured and TestNG as test framework. This framework consists of:-

  1. REST Assured – 4.3.3
  2. Java 8 or above
  3. TestNG – 7.4.0
  4. Maven – 3.8.1

Steps to setup Rest API Test Automation Framework with REST Assured and TestNG

  1. Download and Install Java on system
  2. Download and setup Eclipse IDE on system
  3. Setup Maven
  4. Create a new Maven Project
  5. Add REST Assured and TestNG dependencies to the project
  6. Create a TEST file under src/test/java to write the test code.
  7. Run the tests as TestNG Tests
  8. Run the tests from TestNG.xml
  9. TestNG Report Generation

Detailed Step Description

Step 1- Download and Install Java

Java needs to be present on the system to run the tests. Click here to know How to install Java. To know if Java is installed or not on your machine, type this command in the command line. This command will show the version of Java installed on your machine.

java -version

Step 2 – Download and setup Eclipse IDE on system

The Eclipse IDE (integrated development environment) provides strong support for Java developer which is needed to write Java code. Click here to know How to install Eclipse.

Step 3 – Setup Maven

To build a test framework, we need to add a number of dependencies to the project. It is very tedious and cumbersome process to add each dependency manually. So, to overcome this problem, we use a build management tool. Maven is a build management tool which is used to define project structure, dependencies, build, and test management. Click here to know How to install Maven.

To know if Maven is already installed or not on your machine, type this command in the command line. This command will show the version of Maven installed on your machine.

mvn -version

Step 4 – Create a new Maven Project

Click here to know How to create a Maven project

Below is the Maven project structure. Here,

Group Id – com.example
Artifact Id – RestAssured_TestNG_Demo
Version – 0.0.1-SNAPSHOT
Package – com. example.RestAssured_TestNG_Demo

Step 5 – Add REST Assured and TestNG dependencies to the project

Add below mentioned REST Assured and TestNG dependencies to the project.

<dependencies>
 <!-- https://mvnrepository.com/artifact/org.testng/testng -->
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>7.4.0</version>
      <scope>test</scope>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
   <dependency>
     <groupId>io.rest-assured</groupId>
     <artifactId>rest-assured</artifactId>
     <version>4.3.3</version>
     <scope>test</scope>
    </dependency>
</dependencies>

To create a JSONObject body for the request, we need to add below dependencies to the Test Framework.

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20210307</version>
</dependency> 

Step 6 – Create a TEST file under src/test/java to write the test code.

To know how to create a JSON Request body using JSONObject, please refer this tutorial.

To know more about priority in TestNG, please refer this tutorial.

public class API_Test {

	@Test(description = "To get the details of employee with id 2", priority = 0)
	public void verifyUser() {

		// Given
		given()
		
        // When
		.when()
              .get("http://dummy.restapiexample.com/api/v1/employee/2")
				
         // Then
		 .then()
                .statusCode(200)
                .statusLine("HTTP/1.1 200 OK")
				// To verify booking id at index 3
				.body("data.employee_name", equalTo("Garrett Winters"))
				.body("message", equalTo("Successfully! Record has been fetched."));
	}

	@Test(description = "To create a new employee", priority = 1)
	public void createUser() {

		JSONObject data = new JSONObject();

		data.put("employee_name", "APITest");
		data.put("employee_salary", "99999");
		data.put("employee_age", "30");

		
		// GIVEN
		given()
               .baseUri("http://dummy.restapiexample.com/api")
               .contentType(ContentType.JSON)
               .body(data.toString())

		// WHEN
		.when()
               .post("/v1/create")

		// THEN
		.then()
               .statusCode(200)
               .body("data.employee_name", equalTo("APITest"))
			   .body("message", equalTo("Successfully! Record has been added."));

	}

}

Step 7 – Test Execution through TestNG

Go to Runner class and right click Run As TestNG Test. The tests will run as TestNG tests.

This is how the execution console will look like.

Step 8 – Run the tests from TestNG.xml

Create a TestNG.xml as shown below and run the tests as TestNG. Here, the tests are present in class – com.example.Selenium_TestNGDemo.API_Test.

<?xml version = "1.0"encoding = "UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name = "Suite1">
  <test name = "Test Demo">
    <classes>
          <class name = "com.example.Selenium_TestNGDemo.API_Test"/>
     </classes>  
   </test>
</suite>

Step 9 – TestNG Report Generation

After test execution, refresh the project, a new folder with name test-output will be generated. This folder contains the reports generated by TestNG. The structure of folder test-output looks like as shown below.

We are interested in ’emailable-report.html’ report. Open ’emailable-report.html’, as this is a html report open it with browser. Below image shows emailable-report.html.

TestNG also produce “index.html” report and it resides under test-output folder. Below image shows index.html report. This report contains the high level summary of the tests.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Extraction from JSON in Rest Assured

HOME

In this tutorial, I will explain how can we extract body from JSON Response in Rest Assured. This is needed for the assertion of tests. In t he previous tutorial, I have explained various types of Assertions can be done on JSON Request using Hamcrest.

JsonPath is available at the Central Maven Repository. Maven users add this to the POM.

<!-- https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path -->
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.6.0</version>
</dependency>

If the project is Gradle, add below dependency in build.gradle.

 testImplementation 'com.jayway.jsonpath:json-path:2.6.0'

JsonPath expressions can use the dot–notation.

$.store.book[0].title

or the bracket–notation

$['store']['book'][0]['title']

Below are the most commonly used expressions.

Expression Description
$ The root object or array.
.property Selects the specified property in a parent object.
[‘property’] Selects the specified property in a parent object. Be sure to put single quotes around the property name.Tip: Use this notation if the property name contains special characters such as spaces, or begins with a character other than A..Za..z_.
[n] Selects the n-th element from an array. Indexes are 0-based.
[index1,index2,…] Selects array elements with the specified indexes. Returns a list.
..property Recursive descent: Searches for the specified property name recursively and returns an array of all values with this property name. Always returns a list, even if just one property is found.
* Wildcard selects all elements in an object or an array, regardless of their names or indexes.
[start:end]
[start:]
Selects array elements from the start index and up to, but not including, end index. If end is omitted, selects all elements from start until the end of the array. Returns a list.
[:n] Selects the first n elements of the array. Returns a list.
[-n:] Selects the last n elements of the array. Returns a list.
[?(expression)] Selects all elements in an object or array that match the specified filter. Returns a list.
[(expression)] Script expressions can be used instead of explicit property names or indexes. An example is [(@.length-1)] which selects the last item in an array. Here, length refers to the length of the current array rather than a JSON field named length.
@ Used in filter expressions to refer to the current node being processed.

Below is the sample JSON which I am using for extraction examples.

String jsonString = {
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "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
}

To extract all books present in store:-

        String allBooks = JsonPath.read(jsonString, "$..*").toString();
		System.out.println("--------------- All books in the store --------------");
		System.out.println(allBooks);

Below are examples which shows how to extract different nodes from a JSON Body. I have used above JSON Body for these examples.

        // All bicycles in the store
		String allBicycles = JsonPath.read(jsonString, "$..bicycle").toString();
		System.out.println("--------------- All bicycles in the store ---------------");
		System.out.println(allBicycles);

		// The number of books
		String noOfBooks = JsonPath.read(jsonString, "$..book.length()").toString();
		System.out.println("--------------- The number of books ---------------");
		System.out.println(noOfBooks);

		// The authors of all books
		String authors = JsonPath.read(jsonString, "$.store.book[*].author").toString();
		System.out.println("--------------- Author of all Books ---------------");
		System.out.println(authors);

		// All authors
		String allAuthors = JsonPath.read(jsonString, "$..author").toString();
		System.out.println("--------------- All Authors ---------------");
		System.out.println(allAuthors);

		// All details of the store
		String store = JsonPath.read(jsonString, "$.store.*").toString();
		System.out.println("--------------- All details of the store ---------------");
		System.out.println(store);

		// Price of store
		String storePrice = JsonPath.read(jsonString, "$.store..price").toString();
		System.out.println("--------------- price of store ---------------");
		System.out.println(storePrice);

Below are the examples where I have extracted specific book (nodes) from the JSON body.

	    // Third book
		String thirdBook = JsonPath.read(jsonString, "$..book[2]").toString();
		System.out.println("--------------- third book ---------------");
		System.out.println(thirdBook);

		// first Last Book
		String firstLastBook = JsonPath.read(jsonString, "$..book[-1]").toString();
		System.out.println("--------------- first Last Book ---------------");
		System.out.println(firstLastBook);

		// first two Books
		String firstTwoBooks = JsonPath.read(jsonString, "$..book[0,1]").toString();
		System.out.println("--------------- first Two Books ---------------");
		System.out.println(firstTwoBooks);

		// books from index 0 (inclusive) until index 2 (exclusive)
		String booksRange = JsonPath.read(jsonString, "$..book[:2]").toString();
		System.out.println("--------------- books from index 0 (inclusive) until index 2 (exclusive) ---------------");
		System.out.println(booksRange);

		// All books from index 1 (inclusive) until index 2 (exclusive)
		String booksRange1 = JsonPath.read(jsonString, "$..book[1:2]").toString();
		System.out.println("------------ All books from index 1 (inclusive) until index 2 (exclusive) -----------");
		System.out.println(booksRange1);

		// Book number one from tail
		String bottomBook = JsonPath.read(jsonString, "$..book[1:]").toString();
		System.out.println("--------------- Book number one from tail ---------------");
		System.out.println(bottomBook);

Filters are logical expressions used to filter arrays. Below are the examples of a JSONPath expression with the filters.

       // All books in store expensive than 10
		String expensiveBook = JsonPath.read(jsonString, "$.store.book[?(@.price > 10)]").toString();
		System.out.println("--------------- All books in store costlier than 10 ---------------");
		System.out.println(expensiveBook);

		// All books in store that are not "expensive"
		String notExpensiveBook = JsonPath.read(jsonString, "$..book[?(@.price <= $['expensive'])]").toString();
		System.out.println("--------------- All books in store that are not expensive ---------------");
		System.out.println(notExpensiveBook);

		// All books in store that are equal to price 8.95
		String comparePrice = JsonPath.read(jsonString, "$.store.book[?(@.price == 8.95)]").toString();
		System.out.println("--------------- All books in store that are not expensive ---------------");
		System.out.println(comparePrice);

		// All books matching regex (ignore case)
		String regxExample = JsonPath.read(jsonString, "$..book[?(@.author =~ /.*REES/i)]").toString();
		System.out.println("--------------- All books matching regex (ignore case) ---------------");
		System.out.println(regxExample);

		// All books with price equal to mentioned list of prices
		String priceList = JsonPath.read(jsonString, "$..book[?(@.price in ['12.99', '8.99'])]").toString();
		System.out.println("--------------- All books with price equal to mentioned list of prices ---------------");
		System.out.println(priceList);

		// All books with price NOT equal to mentioned list of prices
		String excludePriceList = JsonPath.read(jsonString, "$..book[?(@.price nin ['12.99', '8.99'])]").toString();
		System.out.println("---------- All books with price NOT equal to mentioned list of prices ---------");
		System.out.println(excludePriceList);

		// All books with specified substring (case-sensitive)
		String substringExample = JsonPath.read(jsonString, "$..book[?(@.author contains 'Melville')]").toString();
		System.out.println("--------------- All books with specified substring (case-sensitive) ---------------");
		System.out.println(substringExample);

		// All books with an ISBN number
		String specificBook = JsonPath.read(jsonString, "$..book[?(@.isbn)]").toString();
		System.out.println("--------------- All books with an ISBN number ---------------");
		System.out.println(specificBook);

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Assertion of JSON in Rest Assured using Hamcrest

HOME

What is Assertion?

Assertion is a way to verify that the expected result and the actual result matches or not in the test case.  A test is considered successful ONLY if it is completed without throwing any exception. If the current value and the expected value match then the assertion passes and when the assertion passes nothing happens. But when an assertion fails it will fail the test case.

There are various ways to perform assertions in API Testing. For API Testing, we are using Rest Assured which uses either Hamcrest or JUnit assertions. We are going to discuss Hamcrest Assertions here.

What is Hamcrest?

Hamcrest is a framework for writing matcher objects allowing ‘match’ rules to be defined declaratively. We do not need to add Hamcrest depdendency explicitly as Rest-Assured 4.3.3 version include by itself. To know more about Hamcrest, please refer this link.

Below is an example of JSON Response. I will perform various assertions on this JSON Response.

To use hamcrest assertion please import the Matchers class static member.

Number related assertions

  1. equalTo – It checks whether the retrieved number from response is equal to the expected number.
  2. greaterThan – checks extracted number is greater than the expected number.
  3. greaterThanOrEqualTo – checks whether the extracted number is greater than equal to the expected number.
  4. lessThan – It checks whether the retrieved number from response is lesser than to the expected number.
  5. lessThanOrEqualTo – It checks whether the retrieved number from response is lesser than or equal to the expected number.

Below assertions are imported from package shown below:-

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.hamcrest.Matchers.lessThan;

Below are the examples to show the use of number related assertions.

public class HamcrestExample {

	public String endpoint = "https://restful-booker.herokuapp.com/booking/1";

	@Test
	public void numberAssertions() {
		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint).then()
                   .body("totalprice", equalTo(813));

		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("totalprice",greaterThan(500));

		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("totalprice",greaterThanOrEqualTo(500));

		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("totalprice",lessThan(1000));

		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("totalprice",lessThanOrEqualTo(1000));

	}
}

String related Assertions

  1. equalTo – It checks whether the extracted string from JSON is equal to the expected string.
  2. equalToIgnoringCaseIt checks whether the extracted string from JSON is equal to the expected string without considering the case (small or capital).
  3. equalToIgnoringWhiteSpace – It checks whether the extracted string from JSON is equal to the expected string by considering the white spaces.
  4. containsString – It checks whether the extracted string from JSON contains the expected string as a substring.
  5. startsWith It checks whether the extracted string from JSON is starting with a given string or character.
  6. endsWith It checks whether the extracted string from JSON is ending with a given string or character.

Below assertions are imported from package shown below:-

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.hamcrest.Matchers.startsWith;
import static org.hamcrest.Matchers.equalToIgnoringWhiteSpace;

Below are the examples to show the use of string related assertions.

public class HamcrestExample {

	public String endpoint = "https://restful-booker.herokuapp.com/booking/1";

	@Test
	public void stringAssertions() {
		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("firstname",equalTo("Mark"));

		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("firstname",equalToIgnoringCase("MARk"));

		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("firstname",containsString("Mark"));

		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("firstname",startsWith("M"));

		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("firstname",endsWith("k"));

        RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("firstname",equalToIgnoringWhiteSpace("   Mark "));


	}
}
  1. nullValue – It checks whether the extracted response from JSON is NULL or Not.
  2. hasKey – It checks whether the extracted map has an expected key.

Below assertions are imported from package shown below:-

import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;

Below are the examples to show the use of collection related assertions.

public class HamcrestExample {

	public String endpoint = "https://restful-booker.herokuapp.com/booking/1";

	@Test
	public void collectionAssertions() {
		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("totalprice1",is(nullValue()));

		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("bookingdates",hasKey("checkin"));

	}
}

Not Assertion

The not assertion inverts the meaning of the other assertions. For example, if you want to perform negative assertions, then we can use any assertions with NOT.

Below assertion is imported from package shown below:-

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;

Below are the examples to show the use of negative assertions.

public class HamcrestExample {

	public String endpoint = "https://restful-booker.herokuapp.com/booking/1";

	@Test
	public void negativeAssertions() {
		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint)
                   .then().body("totalprice",not(equalTo(874)));

	}
}

Multiple Assert Statements

In the below exaple, all 3 asserstions will fail, but it will only execute assertion and first assertion is failed, then other assertions will not be executed.

public class HamcrestExample {

	public String endpoint = "https://restful-booker.herokuapp.com/booking/1";

	@Test
	public void test() {
		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint).then()
                   .body("firstname", equalTo("Jim")) // will fail
				   .body("lastname", equalTo("Smith")) // will fail
				   .body("totalprice", equalTo(314)); // will fail
	}

}

To execute all the assertions present in the test case we have to combine all the assertion into a single body, just like below. You can see that all the assertions are failed and they are shown in the response.

public class HamcrestExample {

	public String endpoint = "https://restful-booker.herokuapp.com/booking/1";

	@Test
	public void test() {
		RestAssured.given().contentType(ContentType.JSON)
                   .when().get(endpoint).then()
                   .body("firstname", equalTo("Jim"), // will fail																												
				   "lastname", equalTo("Smith"), // will fail
				   "totalprice", equalTo(314)); // will fail
	}

}

I have tried to show the use of few of the most commonly used assertion methods. There are many more methods avilable in Hamcrest package. To know about other methods, write import static org.hamcrest.Matchers and add (.) at the end, it will show the list of all the methods available in Hamcrest.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

How to create JSON Array Request Body

HOME

In the last tutorial, I explained  How to test POST JSON Object request using Java Map in Rest Assured . In this tutorial, I will create a request body using JSON Array in Rest Assured. This request body can be used for POST or PUT operations.

What is JSONArray?

JSONArray represents an immutable JSON array (an ordered sequence of zero or more values). It also provides an unmodifiable list view of the values in the array.

  1. JSON array can store multiple value types. The values in a JSONArray can be of the following types: JsonObject, JsonArray, JsonString, JsonNumber, JsonValue.TRUE, JsonValue.FALSE, and JsonValue.NULL.

2. The array index begins with 0.

3. The square brackets [ ] are used to declare the JSON array.

An API may accept a JSON Array payload as a request body. Imagine, we want to add employee details of more than one employee in the below example. In this case, we can pass multiple JSON objects within a JSON array. I have explained 2 ways to create JSON Object – map or JsonObject. Refer to any one of the tutorials to get to know about the creation of JSON Object.

To create a JSON Array, we need to add a maven dependency, as shown below.

<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20210307</version>
</dependency>  

JSONObject is imported from package:-

import org.json.JSONObject;

JSONArray is imported from package:-

import org.json.JSONArray;

Below is an example of JSONArray.

How to create JSONArray Request Body or payload?

  1. Create a JSON Object and add the first employee details.
  2. Create another JSON Object and add second guest details
  3. Create a JSONArray.
  4. Add both JSON Objects to JSONArray.

Below is an example of creating a request from JSONArray with multiple JSON Objects.  I am using a logger just to print the JSON body in the Console. 

public class RequestBodyAsJSONArrayDemo {

	@Test
	public void passBodyAsJsonArrayDemo() {

		// JSON Object for first employee
		JSONObject data1 = new JSONObject();

		data1.put("employee_name", "ObjectTest");
		data1.put("profile_image", "test1.png");
		data1.put("employee_age", "30");
		data1.put("employee_salary", "11111");

		// JSON Object for second employee
		JSONObject data2 = new JSONObject();

		data2.put("employee_name", "MapTest");
		data2.put("profile_image", "test2.png");
		data2.put("employee_age", "20");
		data2.put("employee_salary", "99999");

		// Creating JSON array to add both JSON objects
		JSONArray array = new JSONArray();
		array.put(data1);
		array.put(data2);

		// Send the request		
        RestAssured.given()
                          .contentType(ContentType.JSON)
                          .body(array.toString())
                          .log().all()
				
				.when()
                       .post("http://dummy.restapiexample.com/api/v1/create")
				
				.then()
                      .assertThat().statusCode(200)
                      .body("message", equalTo("Successfully! Record has been added."))
				      .log().all();
	}
}

Below is the execution screenshot.

Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!

How to test POST JSON Object request using Java Map in Rest Assured

HOME

In the last tutorial, I have explained How to test POST request from JSON Object in Rest Assured where request body is built in JSONObject. In this tutorial, I will create a Request body using JSON Object in Rest Assured. 

We can create a JSON Object using a Map in Java. 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.

I have created a simple Java map and filled it with the values that represent JSON properties.

	@Test
	public void passBodyAsMap() {
		Map<String, String> map = new HashMap<String, String>();
		map.put("employee_name", "MapTest");
		map.put("employee_salary", "99999");
		map.put("employee_age", "30");
		map.put("profile_image", "test.png");
		RestAssured.given()
                          .contentType(ContentType.JSON)
                          .body(map)
                          .log().all()
				
				   .when()
                         .post("http://dummy.restapiexample.com/api/v1/create")
				
				   .then()
                         .assertThat().statusCode(200)
                         .body("data.employee_name", equalTo("MapTest"))
				         .body("data.employee_age", equalTo("30"))
                         .body("data.employee_salary", equalTo("99999"))
				         .body("message", equalTo("Successfully! Record has been added.")).log().all();
	}

The Request body as well as response body will look as shown below:-

Above one is a simple JSON Request Body. Lets take an example of Complex Request Body or nested Request Body as shown below.

@Test
	public void passBodyAsMultipleMap() {
		// First JSON Object using Hash Map
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("employee_name", "MapTest");
		data.put("profile_image", "test.png");
		// Second JSON Object using Hash Map
		Map<String, String> msg = new HashMap<String, String>();
		msg.put("updated_message", "Details of New Resource");
		msg.put("employee_age", "30");
		data.put("details", msg);
		data.put("employee_salary", "99999");
		RestAssured.given().contentType(ContentType.JSON).body(data).log().all()
				// WHEN
				.when().post("http://dummy.restapiexample.com/api/v1/create")
				// THEN
				.then().assertThat().statusCode(200).body("data.employee_name", equalTo("MapTest"))
				.body("data.details.updated_message", equalTo("Details of New Resource"))
				.body("data.details.employee_age", equalTo("30")).body("data.employee_salary", equalTo("99999"))
				.body("message", equalTo("Successfully! Record has been added.")).log().all();
	}
}

The Request body as well as response body will look as shown below image. First part is the body of request and second part is the response provided by API.

Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

How to test POST request from JSON Object in Rest Assured

HOME

In the last tutorial, I have explained How to test POST Request using Rest Assured where request body is in String Format. In this tutorial, I will create a Request body using JSON Object in Rest Assured. This request body can be used for POST or PUT operations.

First, setup a basic Rest Assured Maven Project by clicking here and Gradle project by clicking here.

In the previous post, you must have observed that I had hard-coded the JSON request body in a string format. It is not a good practice if you have the dynamic payload or want to create a payload at run time or parameterized one. It is always recommended to create a payload in such a way that you can easily maintain, manage, update, and retrieve values from it. This can be achieved by JSONObject or JSONArray.

JSONObject is an unordered collection of key and value pairs, resembling Java’s native Map implementations. JSON stores data as a key-value pair. Key is left side and value is the right side and a semicolon is used to separate both. One key-value pair is separated from another key-value pair using comma (,).

The internal form is an object having to get and opt methods for accessing the values by name and put methods for adding or replacing values by name. The values can be any of these types: Boolean, JSONArray, JSONObject, Number, String, or the JSONObject.NULL object.

To create a request body using JSON Object, we need to add a maen dependency.

<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20210307</version>
</dependency>   

JSONObject is imported from package:-

import org.json.JSONObject;

JSONObject exposes an API similar to Java’s Map interface. Below is an example of creating a request from JSON Object. Here, Id is auto-generated attribute. We are using the put() method and supply the key and value as an argument. I am using a logger just to print the JSON body in the Console. 

@Test
	public void passBodyAsJsonObject() {

		JSONObject data = new JSONObject();

		data.put("employee_name", "MapTest");
		data.put("profile_image", "test.png");
		data.put("employee_age", "30");
		data.put("employee_salary", "11111");

		
		RestAssured.given()
                      .contentType(ContentType.JSON)
                      .body(data.toString())
                      .log().all()
			
				  .when()
                      .post("http://dummy.restapiexample.com/api/v1/create")
				
				  .then()
                       .assertThat().statusCode(200)
                       .body("data.employee_name", equalTo("MapTest"))
				       .body("data.employee_age", equalTo("30"))
                       .body("data.employee_salary", equalTo("11111"))
				       .body("data.profile_image", equalTo("test.png"))
				       .body("message", equalTo("Successfully! Record has been added."))
                       .log().all();

	}

The Request body will look as shown below:-

The texts produced by the toString() methods strictly conform to the JSON syntax rules.

 .body(data.toString())

Above one is a simple JSON Request Body. Lets take an example of Complex Request Body or nested Request Body.

We need to create two JSONObject here. One will hold overall key-value pairs and another JSONObject will hold only employee_details key-value pairs. 

Below is the example which shows how to create a complex JSON request body using JSONObject.

@Test
	public void passBodyAsJsonObjectDemo() {
        
        //First JSONObject
		JSONObject data = new JSONObject();

		data.put("profile_image", "test.png");
        
        //Second JSONObject
		JSONObject detail = new JSONObject();

		detail.put("updated_message", "Details of New Resource");
		detail.put("employee_age", "30");

		data.put("employee_details", detail);

		data.put("employee_name", "MapTest");
		data.put("employee_salary", "11111");

		
		RestAssured.given()
                         .contentType(ContentType.JSON)
                         .body(data.toString())
                         .log().all()
				
				    .when()
                          .post("http://dummy.restapiexample.com/api/v1/create")
				
				    .then()
                           .assertThat().statusCode(200)
                           .body("data.employee_name", equalTo("MapTest"))
				           .body("data.employee_details.employee_age", equalTo("30"))
				           .body("data.employee_details.updated_message", equalTo("Details of New Resource"))
				           .body("data.employee_salary", equalTo("11111")).body("data.profile_image", equalTo("test.png"))
				          .body("message", equalTo("Successfully! Record has been added."))
                          .log().all();
	}
}

The Request body will look as shown below:-

We are done. Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!