Showing posts with label Rest Assured API Testing. Show all posts
Showing posts with label Rest Assured API Testing. Show all posts

How to test Graph QL API in Rest Assured

 



What is GraphQL APIs?

GraphQL is an open-source query language for APIs and a server-side runtime for executing those queries. It's essentially a protocol that dictates how a client (like a mobile app or website) can request data from a server, providing a more efficient and flexible alternative to traditional API designs like REST.


Core Theory and Concepts

GraphQL is built around a few key theoretical concepts:


1. Schema and Type System

A GraphQL Schema is the central component and acts as a contract between the client and the server. It uses a Strongly-Typed system to precisely define all the data that a client can request.

  • Types: The schema defines the structure of data in terms of Object Types, which are named collections of fields. For example, a User type might have name, email, and posts fields.
  • Fields: These are the units of data that can be requested on a type. Each field has a defined data type (like String, Int, or another custom Object Type). The presence of these types allows for validation of a query before execution and ensures predictable responses.


2. Client-Specified Requests

This is the most significant departure from traditional APIs. In GraphQL, the client declares exactly what data it needs in a single request.
  • Queries: These are used to fetch data. A client sends a query that mirrors the structure of the data it expects to receive. The server then returns a response that contains only the requested fields, which solves the problem of over-fetching (getting more data than you need) common in fixed-endpoint APIs.
  • Mutations: These are used to modify data (create, update, or delete). Like queries, they specify the data that should be changed and the desired data to be returned after the change is complete.
  • Subscriptions: These enable real-time data streams, allowing a client to subscribe to a specific event and receive updates from the server whenever that data changes.

3. Single Endpoint

Unlike a traditional REST API, which may expose many different endpoints (URLs) for different resources (e.g., /users, /posts/123), a GraphQL API typically exposes only a single endpoint. All data fetching and modification requests are sent to this one URL, with the specific operation (query or mutation) and the requested data shape defined in the request body.


4. Resolvers

While the schema defines what data can be fetched, Resolvers define how to actually retrieve that data for each field in the schema.
  • A resolver is a function associated with a specific field on a type.
  • When a client sends a query, the GraphQL server executes the relevant resolver functions for all the requested fields.
  • Resolvers act as the bridge between the GraphQL layer and the underlying data sources (like databases, microservices, or even other REST APIs). They hide the complexity of the back-end from the client, meaning the client only sees a unified "graph" of data.

Key Benefits
  • Efficiency: Clients only get the data they ask for, minimizing data transfer, which is especially beneficial for mobile applications and limited bandwidth.
  • Flexibility: The client controls the data requirements, allowing for rapid front-end changes without requiring the back-end to change fixed endpoints.
  • API Evolution: New fields can be added to the schema without affecting existing clients, allowing the API to evolve without needing disruptive versioning (like v1, v2).

To validate a GraphQL API using Rest Assured in Java, follow these key steps:















Public GraphQL API for Example

We'll use the public GraphQL API from https://countries.trevorblades.com/

Endpointhttps://countries.trevorblades.com/








Example Query (returns name and capital of India):


{
  country(code: "IN") {
    name
    capital
  }
}




Java Code Using Rest Assured

import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.json.JSONObject;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;

public class GraphQLApiTest {

    public static void main(String[] args) {

        // GraphQL query as string
        String query = "{ country(code: \"IN\") { name capital } }";

        // Prepare the JSON body
        JSONObject requestBody = new JSONObject();
        requestBody.put("query", query);

        // Set base URI
        RestAssured.baseURI = "https://countries.trevorblades.com/";

        // Send POST request and validate response
        given()
            .header("Content-Type", "application/json")
            .body(requestBody.toString())
        .when()
            .post()
        .then()
            .statusCode(200)
            .body("data.country.name", equalTo("India"))
            .body("data.country.capital", equalTo("New Delhi"));
    }
}



Code explanation: 

(a) Define Graph ql query in string form
(b) Define json body by using JSONObject class
(c) Define base URI
(d) Set POST request
(e) Get response and validate response.


Validations Performed

  • HTTP status code = 200

  • Country name = "India"

  • Capital = "New Delhi"



Maven Dependencies:

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>5.3.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20210307</version>
</dependency>


Suggested Posts:

1. Test Basic Authentication of API in RestAssured
2. Validate Request and Response by POJO in RestAssured
3. Extract Response by JSONPath in RestAssured
4. Validate Keys in API in RestAssured
5. How to Test SOAP API in RestAssured

How to Validate Keys in API in Rest Assured

 



To validate that a JSON response body contains a specific key using hasKey() from Hamcrest Matchers in Rest Assured, 

follow this step-by-step guide using the endpoint:


1. Send API Request

  • Use Rest Assured to send an HTTP request (GET, POST, etc.) to the API endpoint.
  • Capture the response in a Response object

2. Extract JSON Response

  • Convert the response body into a JSON object using Rest Assured’s inbuilt methods.
  • This allows easy access to keys and values.

3. Check for Key Existence
  • Extract the JSON as a map or use JSONPath.
  • Validate whether specific keys are present in the response.
  • Example: If response has { "id": 101, "name": "Alex" }, you should check whether keys id and name exist.

4. Assertion for Keys
  • Use assertions (assertThat, containsKey, hasKey) to ensure that expected keys exist in the response.
  • This guarantees that the API contract is maintained.

5. Validate Nested Keys
  • For JSON objects with nested structures, you can use dot notation in JSONPath to check sub-keys.
  • Example: "address.city" should exist inside "address".

6. Schema Validation (Optional)
  • Instead of validating keys one by one, you can use a JSON Schema file.
  • Schema validation ensures all required keys are present with correct data types.









URL: https://reqres.in/api/users?page=2






Goal: Validate that the JSON response has a key like "page""data", etc.


Code Example in Java (Rest Assured + Hamcrest hasKey())

import io.restassured.RestAssured;
import io.restassured.response.Response;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

public class HasKeyExample {
    public static void main(String[] args) {
        RestAssured.baseURI = "https://reqres.in";

        given()
        .when()
            .get("/api/users?page=2")
        .then()
            .statusCode(200)
            .body("$", hasKey("page"))          // top-level key
            .body("$", hasKey("per_page"))      // another top-level key
            .body("$", hasKey("data"))          // array of users
            .body("support", hasKey("url"))     // nested key inside "support"
            .body("support", hasKey("text"));   // another nested key
    }
}




Code explanation: 

(a) In main method, set base URI
(b) Send request to api and get response.
(c) In response body, we have to use hasKey() to validate Json keys as shown in the code.


Explanation:

  • "$" refers to the root of the JSON response.
  • hasKey("keyName") checks if a key exists at that JSON level.
  • body("support", hasKey("url")) checks if the support object has a url key.



Sample Response from https://reqres.in/api/users?page=2

Below is the json resposne of the API, having json elements like key-value pairs of page,per_page,total,etc.

{
    "page": 2,
    "per_page": 6,
    "total": 12,
    "total_pages": 2,
    "data": [...],
    "support": {
        "url": "https://reqres.in/#support-heading",
        "text": "To keep ReqRes free, contributions towards server costs are appreciated!"
    }
}



Maven Dependencies

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>5.3.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest</artifactId>
    <version>2.2</version>
</dependency>


Suggested Posts:

1. Validate API Response from Database in RestAssured
2. Validate JSON Schema in RestAssured
3. Extract Response by JSONPath in RestAssured
4. Validate Keys in API in RestAssured
5. How to Test SOAP API in RestAssured

How to validate API Response from Database in Rest Assured

 



Validating an API Response against the Database in Rest Assured means checking whether the data returned by the API is consistent with the actual data stored in the backend database. This ensures that the API is not only returning the correct structure but also the correct content.

To validate an API response against data in a MySQL database using Rest Assured, follow these steps:








Step-by-Step Guide


Step 1: Setup Project with Required Dependencies


<dependencies>
    <!-- Rest Assured for API Testing -->
    <dependency>
        <groupId>io.rest-assured</groupId>
        <artifactId>rest-assured</artifactId>
        <version>5.3.0</version>
        <scope>test</scope>
    </dependency>

    <!-- MySQL Connector for DB Connection -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>

    <!-- JSON handling -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20230227</version>
    </dependency>

    <!-- TestNG (optional for test framework) -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.4.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>


Step 2: MySQL Database Setup

Suppose you have a table users with structure:

CREATE TABLE users (
    id INT PRIMARY KEY,
    email VARCHAR(255),
    first_name VARCHAR(100),
    last_name VARCHAR(100),
    avatar VARCHAR(255)
);



Insert some matching test data from https://reqres.in/api/users?page=2


















Step 3: Java Code

import io.restassured.RestAssured;
import io.restassured.response.Response;

import java.sql.*;
import java.util.List;
import java.util.Map;

import static io.restassured.RestAssured.given;

public class APIDatabaseValidation {

    // JDBC details
    static final String DB_URL = "jdbc:mysql://localhost:3306/testdb";
    static final String USER = "root";
    static final String PASS = "password";

    public static void main(String[] args) throws Exception {
        // Step 1: Get API response
        RestAssured.baseURI = "https://reqres.in";
        Response response = given()
                .when()
                .get("/api/users?page=2")
                .then()
                .statusCode(200)
                .extract().response();

        // Step 2: Extract JSON data from API
        List<Map<String, Object>> apiUsers = response.jsonPath().getList("data");

        // Step 3: Connect to MySQL and validate
        Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
        Statement stmt = conn.createStatement();

        for (Map<String, Object> apiUser : apiUsers) {
            int id = (Integer) apiUser.get("id");
            String email = (String) apiUser.get("email");
            String firstName = (String) apiUser.get("first_name");
            String lastName = (String) apiUser.get("last_name");
            String avatar = (String) apiUser.get("avatar");

            // Query DB for this user
            String query = "SELECT * FROM users WHERE id = " + id;
            ResultSet rs = stmt.executeQuery(query);

            if (rs.next()) {
                assert email.equals(rs.getString("email")) : "Email mismatch for ID " + id;
                assert firstName.equals(rs.getString("first_name")) : "First name mismatch for ID " + id;
                assert lastName.equals(rs.getString("last_name")) : "Last name mismatch for ID " + id;
                assert avatar.equals(rs.getString("avatar")) : "Avatar mismatch for ID " + id;
                System.out.println("User ID " + id + " matched successfully.");
            } else {
                System.err.println("User ID " + id + " not found in database.");
            }
            rs.close();
        }

        // Close DB connection
        stmt.close();
        conn.close();
    }
}


Code explanation: 

(a) Define database details like db username, db password, db url, before main method
(b) In main method, define base URI, send API request and extract data from json response in a map object which is wrapped in a List object.
(c) Create a JDBC connection to the database
(d) Iterate map object by for loop and stored data in string objects
(e) Get data from database using ResultSet object and assert the data with string data that we got from list.
(f) Finally, close the database connection.



Points to Consider
  • Always ensure you are pointing to the same environment (API and DB should be connected to same Test/Stage DB).
  • Handle null values, trimming spaces, and data type mismatches while comparing.
  • Validate not just single records, but also multiple records if the API returns a list.
  • For performance testing, check if the response time of the API aligns with fetching from DB.

Suggested Posts:

1. Validate XML Schema in RestAssured
2. Validate JSON Schema in RestAssured
3. Extract Response by JSONPath in RestAssured
4. Validate Response by Matchers API in RestAssured
5. How to Test SOAP API in RestAssured