Quality Assurance

Validate API Calls Using Rest Assured in Singleton Design Pattern

Introduction

Application Programming Interface becomes the backbone of programming, which helps in communicating between two different systems. As a tester, we need to give maximum test coverage for API calls validation in integration testing. This can be achieved by automating the API calls to increase efficiency.

Rest API calls will be validated using different open-source automation tools like SoapUI, Katalon studio, Rest-Assured, Karate, etc.

Here we are going to discuss Rest Assured libraries for validating API calls. The first step is to get this library integrated with the java projects. These library classes facilitate the developer/tester in framing the request with different parameters and helps in retrieving the response in standard formats like XML/JSON and helps in taking logs of request and response details for each API call.

Pre-requisites

The reader should be aware of creating Maven Project in any IDE like Eclipse, IntelliJ, Atom having basic knowledge about API calls.

Components in Rest-Assured

The significant functionality of the Rest Assured library is Request and Response. Request functionality covers composing of Base URI, Resource Path, Query / Form parameters, Authorization keys, Header, and Body. Then request call is made by any methods like GET, POST, PUT and more to the server and retrieve its response. For composing the request, we have Request Specification and RequestSpecBuilder classes in the Rest-Assured library.

Covid 19
COVID-19: Digital Insights For Enterprise Action

Access Perficient’s latest insights into how you can leverage digital technologies to not only respond to the pandemic, but drive your operations forward and deliver experiences your customers need.

Get Informed

For validating the response received from the server, we have a Response class. It helps extract the response content as JSON/XML format, to verify status, response header & body. It supports to handle the storing of request and response logs while making validation of calls using RequestLoggingFilter and ResponseLoggingFilter classes.

Singleton class has one instance of common request forming and response validation. It provides global access to the instance, so here framing requests, retrieving responses, and logs are easily handled for code reusability.

Demonstrate API calls validation using Singleton Design Pattern

Let’s see the below example,

  • Add Book details in the record using the POST method
  • Retrieve Book details under author name using the GET method
Method URL Format Purpose
POST https://BaseURI/ResourcePath To add book details in the Record
GET https://BaseURI/ResourcePath?QueryParam=Value To get Book with author-name

Steps to automate these API using Rest-Assured Libraries

Step 1: Create a Maven Project with dependency

Include latest TestNG and Rest-Assured dependencies in pom.xml file

<dependencies>
  <dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>7.1.0</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>4.1.2</version>
    <scope>compile</scope>
  </dependency>
</dependencies>

Step 2: Create a Singleton class for handling major actions.

For singleton class, the static instance variable here is SingletonRA RA, which can be instantiated only in its class for once.  Here the request is formed in two-stages, The first one in the respect method the standard headers, forming the log file, and in the second stage of request with service-specific details like query, params are added in variable res in getRes method.

package RestAssured;

import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.filter.log.RequestLoggingFilter;
import io.restassured.filter.log.ResponseLoggingFilter;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Paths;

public class SingletonRA
{
   /*Private Constructor*/
    private SingletonRA() {}
    /*single instance variable of the class*/
    private static SingletonRA RA;
    /*creating instance of singleton class*/
    public static SingletonRA getInstance()
    {
        if(RA ==null)
        {
            RA = new SingletonRA();
        }
        return RA;
    }

    /*RequestSpecification used to form basic request*/
    public RequestSpecification reqSpec() throws FileNotFoundException {
        RequestSpecification req = new RequestSpecBuilder()
                .setBaseUri("http://baseuri")
                .addFilter(RequestLoggingFilter.logRequestTo(new PrintStream(new FileOutputStream("log1.txt"))))
                .addFilter(ResponseLoggingFilter.logResponseTo(new PrintStream(new FileOutputStream("log.txt"))))
                .setContentType(ContentType.JSON).build();
        return req;
    }

    /* Obtaining Response by providing particular resource and  
     * payload specific to services 
     * in the RequestSpecification from reqSpec */  
    /* To use single getRes method for all protocol, making path variable as
     * optional in this method, Say for POST method  we need resource and payload 
     * path but for GET method variable resource alone sufficient.*/

    public Response getRes(String resource,String... path){
        RequestSpecification res;
        Response response = null;

    /*Optional variable comes as array so convert them into string*/
        StringBuffer sb =new StringBuffer();
        for(int i=0;i<path.length;i++) {
            sb.append(path[i]);
        }
        
        try{
        
        /*For Adding Book using POST method*/   
            if(resource.contains("Library/Addbook.php")){
                res = RestAssured.given().spec(reqSpec()).
                        body(GenerateStringFromResource(sb.toString()));
                response =res.when().post(resource);
                return response;
            }
        /*For retrieve Book details using Author in GET Method*/ 
        else if (resource.contains("Library/GetBook.php")){
                
                res = RestAssured.given().spec(reqSpec()).queryParam("AuthorName","Selva");
                response = res.when().get(resource);
                return response;
            }
            
        }catch(Exception e){
            e.printStackTrace();
        }
        return response;
    }

    /*Load payload from json file*/
    public static String GenerateStringFromResource(String path) throws IOException {
        return new String(Files.readAllBytes(Paths.get(path)));
    }

}

Step 3: Create a Test class for writing TestNG tests.

For the Post method, we need to pass the payload and resource to get a response, and for the GET method, the only help is required to be given. Here for adding Book details into a record, we are passing Payload in Json file location. The resource for each request differs, so each service needs to test with its resources passing through Tests.

package RestAssured;

import java.util.ArrayList;

import org.testng.annotations.Test;

import io.restassured.path.json.JsonPath;

public class TestRA
{
    /*Get instance of singleton class*/  
    SingletonRA RA = SingletonRA.getInstance();
    
    @Test
    public void addBook(){
        String payloadPath =".\\src\\resources\\postBook.json";
        String resource = "Library/Addbook.php";
        /*Pass the payload location and resource for the API*/  
        String Response = RA.getRes(resource,payloadPath).asString();
        
        /*Using Jsonpath get msg field in response*/  
        JsonPath js = new JsonPath(Response);
        String msg = js.getString("msg");
        
        /*Validate the msg and display corresponding display message*/ 
        if(msg.contains("operation failed")) {
            System.out.println("Given Book details are already present in record");
        }else if(msg.contains("successfully")) {
            System.out.println("Given Book details are added in record");
        }else {
            System.out.println("Rest API is not working as expected");
        }
    }
    
    @Test
    public void getBookbyAuthor() {
        String resource = "Library/GetBook.php";
        /*Pass the resource to get response*/
        String Response = RA.getRes(resource).asString();
        JsonPath js = new JsonPath(Response);
        System.out.println(js.get("book_name"));
        ArrayList<String> books = js.get("book_name");
        
         /*Verify the count of books present under author name*/
        if(books.size()>0) {
            System.out.println(books.size() + " Books are present for the author");
        }
        
    }
}

Request Log for POST method :

Request method: POST  
Request URI:    http://<baseuri>/Library/Addbook.php  
Proxy:          <none>  
Request params: <none>  
Query params:   <none>  
Form params:    <none>  
Path params:    <none>  
Headers:        Accept=*/*  
                Content-Type=application/json; charset=UTF-8  
Cookies:        <none>  
Multiparts:     <none>  
Body:  
{  
    "name": "Bedtime stories-Kings",  
    "isbn": "KID",  
    "aisle": "006",  
    "author": "Krishna"  
}  

Response Log for POST method :

HTTP/1.1 200 OK  
Date: Fri, 06 Mar 2020 11:04:14 GMT  
Server: Apache  
Access-Control-Allow-Origin: *  
Access-Control-Allow-Methods: POST  
Access-Control-Max-Age: 3600  
Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With  
Keep-Alive: timeout=5, max=100  
Connection: Keep-Alive  
Transfer-Encoding: chunked  
Content-Type: application/json;charset=UTF-8  
  
{  
    "Msg": "successfully added",  
    "ID": "KID006"  
}  

Thanks for spending time reading. Please share your queries and feedback in the comments.

About the Author

Selvanandhini is a Senior Technical Consultant in Perficient India Private limited with 7 years of expertise in Quality Assurance. She has experience in automating tests in various platforms and always like to explore new technologies.

More from this Author

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to the Weekly Blog Digest:

Sign Up