Rest Assured Basics

Setup, GET/POST requests, JSON parsing

What is Rest Assured?

Rest Assured is a Java-based library that simplifies testing and validating REST APIs. It provides a domain-specific language (DSL) for writing powerful, readable tests.

Understanding REST APIs

REST (Representational State Transfer) APIs communicate using HTTP methods:

MethodPurposeExample
GETRetrieve dataGet user details
POSTCreate new resourceCreate new user
PUTUpdate entire resourceUpdate user profile
PATCHPartial updateUpdate user email only
DELETERemove resourceDelete user account

Project Setup

Maven Dependencies

Add these dependencies to your pom.xml:

<dependencies>
    <!-- Rest Assured -->
    <dependency>
        <groupId>io.rest-assured</groupId>
        <artifactId>rest-assured</artifactId>
        <version>5.4.0</version>
        <scope>test</scope>
    </dependency>

    <!-- JSON Schema Validation -->
    <dependency>
        <groupId>io.rest-assured</groupId>
        <artifactId>json-schema-validator</artifactId>
        <version>5.4.0</version>
        <scope>test</scope>
    </dependency>

    <!-- TestNG -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.9.0</version>
        <scope>test</scope>
    </dependency>

    <!-- Jackson for JSON serialization -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.16.0</version>
    </dependency>
</dependencies>

Static Imports

Add these imports to use Rest Assured’s fluent API:

import static io.restassured.RestAssured.*;
import static io.restassured.matcher.RestAssuredMatchers.*;
import static org.hamcrest.Matchers.*;

Your First GET Request

Basic GET Request

The simplest way to make a GET request:

@Test
public void getListOfUsers() {
    given()
        .baseUri("https://reqres.in")
    .when()
        .get("/api/users?page=2")
    .then()
        .statusCode(200)
        .body("page", equalTo(2))
        .body("data.size()", greaterThan(0));
}

Understanding the BDD Pattern

GET with Path Parameters

@Test
public void getSingleUser() {
    int userId = 2;

    given()
        .baseUri("https://reqres.in")
        .pathParam("id", userId)
    .when()
        .get("/api/users/{id}")
    .then()
        .statusCode(200)
        .body("data.id", equalTo(userId))
        .body("data.email", containsString("@"));
}

GET with Query Parameters

@Test
public void getUsersWithQueryParams() {
    given()
        .baseUri("https://reqres.in")
        .queryParam("page", 1)
        .queryParam("per_page", 5)
    .when()
        .get("/api/users")
    .then()
        .statusCode(200)
        .body("per_page", equalTo(5))
        .body("data", hasSize(lessThanOrEqualTo(5)));
}

Extracting Response Data

@Test
public void extractResponseData() {
    Response response = given()
        .baseUri("https://reqres.in")
    .when()
        .get("/api/users/2")
    .then()
        .extract().response();

    // Extract specific values
    String email = response.jsonPath().getString("data.email");
    int id = response.jsonPath().getInt("data.id");
    String firstName = response.path("data.first_name");

    System.out.println("User: " + firstName + " (" + email + ")");

    // Get entire response as String
    String responseBody = response.asString();

    // Get status code
    int statusCode = response.getStatusCode();
}

POST Request with JSON

POST with JSON String

@Test
public void createUserWithJsonString() {
    String requestBody = """
        {
            "name": "John Doe",
            "job": "QA Engineer"
        }
        """;

    given()
        .baseUri("https://reqres.in")
        .contentType(ContentType.JSON)
        .body(requestBody)
    .when()
        .post("/api/users")
    .then()
        .statusCode(201)
        .body("name", equalTo("John Doe"))
        .body("job", equalTo("QA Engineer"))
        .body("id", notNullValue())
        .body("createdAt", notNullValue());
}

POST with HashMap

@Test
public void createUserWithMap() {
    Map<String, Object> requestBody = new HashMap<>();
    requestBody.put("name", "Jane Smith");
    requestBody.put("job", "Developer");

    given()
        .baseUri("https://reqres.in")
        .contentType(ContentType.JSON)
        .body(requestBody)
    .when()
        .post("/api/users")
    .then()
        .statusCode(201)
        .body("name", equalTo("Jane Smith"));
}

POST with POJO (Recommended)

Create a model class for cleaner, type-safe code:

// User.java - POJO class
public class User {
    private String name;
    private String job;

    public User() {}

    public User(String name, String job) {
        this.name = name;
        this.job = job;
    }

    // Getters and Setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getJob() { return job; }
    public void setJob(String job) { this.job = job; }
}
@Test
public void createUserWithPojo() {
    User user = new User("Alex Brown", "Automation Lead");

    given()
        .baseUri("https://reqres.in")
        .contentType(ContentType.JSON)
        .body(user)  // Automatically serialized to JSON
    .when()
        .post("/api/users")
    .then()
        .statusCode(201)
        .body("name", equalTo("Alex Brown"));
}

Deserialize Response to POJO

@Test
public void deserializeResponse() {
    User createdUser = given()
        .baseUri("https://reqres.in")
        .contentType(ContentType.JSON)
        .body(new User("Test User", "Tester"))
    .when()
        .post("/api/users")
    .then()
        .statusCode(201)
        .extract()
        .as(User.class);  // Deserialize to POJO

    Assert.assertEquals(createdUser.getName(), "Test User");
}

Response Validation

Status Code Validation

@Test
public void validateStatusCodes() {
    // Exact match
    given().get("https://reqres.in/api/users/2")
        .then().statusCode(200);

    // Using Hamcrest matchers
    given().get("https://reqres.in/api/users/2")
        .then().statusCode(is(200));

    // Range check
    given().get("https://reqres.in/api/users/2")
        .then().statusCode(both(greaterThanOrEqualTo(200))
                          .and(lessThan(300)));
}

Header Validation

@Test
public void validateHeaders() {
    given()
        .baseUri("https://reqres.in")
    .when()
        .get("/api/users")
    .then()
        .header("Content-Type", containsString("application/json"))
        .header("Connection", equalTo("keep-alive"));
}

JSON Body Validation with JsonPath

@Test
public void validateJsonBody() {
    given()
        .baseUri("https://reqres.in")
    .when()
        .get("/api/users/2")
    .then()
        .statusCode(200)
        // Simple field validation
        .body("data.id", equalTo(2))
        .body("data.email", endsWith("@reqres.in"))
        .body("data.first_name", not(emptyString()))

        // Nested object validation
        .body("support.url", containsString("reqres"))

        // Check field exists
        .body("data", hasKey("avatar"));
}

Array Validation

@Test
public void validateArrayResponse() {
    given()
        .baseUri("https://reqres.in")
    .when()
        .get("/api/users?page=1")
    .then()
        .statusCode(200)
        // Array size
        .body("data.size()", greaterThan(0))
        .body("data", hasSize(6))

        // All items match condition
        .body("data.id", everyItem(greaterThan(0)))
        .body("data.email", everyItem(containsString("@")))

        // Check specific item
        .body("data[0].id", equalTo(1))

        // Find item in array
        .body("data.find { it.id == 1 }.email", notNullValue());
}

Response Time Validation

@Test
public void validateResponseTime() {
    given()
        .baseUri("https://reqres.in")
    .when()
        .get("/api/users")
    .then()
        .time(lessThan(2000L)); // Response time 

Logging & Debugging

Request and Response Logging

@Test
public void loggingExample() {
    given()
        .baseUri("https://reqres.in")
        .log().all()  // Log entire request
    .when()
        .get("/api/users/2")
    .then()
        .log().all()  // Log entire response
        .statusCode(200);
}

Selective Logging

@Test
public void selectiveLogging() {
    given()
        .baseUri("https://reqres.in")
        .log().uri()        // Log only URI
        .log().method()     // Log HTTP method
        .log().headers()    // Log headers
    .when()
        .get("/api/users/2")
    .then()
        .log().status()     // Log status line
        .log().body()       // Log response body
        .statusCode(200);
}

Log on Failure Only

@Test
public void logOnlyOnFailure() {
    given()
        .baseUri("https://reqres.in")
        .log().ifValidationFails()  // Log request if validation fails
    .when()
        .get("/api/users/2")
    .then()
        .log().ifValidationFails()  // Log response if validation fails
        .statusCode(200);
}

Global Configuration

Setting Base URI and Path

public class BaseTest {

    @BeforeClass
    public void setup() {
        // Set base URI for all requests
        RestAssured.baseURI = "https://reqres.in";
        RestAssured.basePath = "/api";

        // Default content type
        RestAssured.requestSpecification = given()
            .contentType(ContentType.JSON)
            .accept(ContentType.JSON);
    }

    @AfterClass
    public void teardown() {
        RestAssured.reset(); // Reset to defaults
    }
}

Request Specification

Create reusable request specifications:

public class ApiSpecs {

    public static RequestSpecification getDefaultSpec() {
        return new RequestSpecBuilder()
            .setBaseUri("https://reqres.in")
            .setBasePath("/api")
            .setContentType(ContentType.JSON)
            .addHeader("Accept", "application/json")
            .log(LogDetail.ALL)
            .build();
    }
}

// Usage in tests
@Test
public void testWithSpec() {
    given()
        .spec(ApiSpecs.getDefaultSpec())
    .when()
        .get("/users/2")
    .then()
        .statusCode(200);
}

Response Specification

public static ResponseSpecification getSuccessSpec() {
    return new ResponseSpecBuilder()
        .expectStatusCode(200)
        .expectContentType(ContentType.JSON)
        .expectResponseTime(lessThan(3000L))
        .build();
}

// Usage
@Test
public void testWithResponseSpec() {
    given()
        .spec(ApiSpecs.getDefaultSpec())
    .when()
        .get("/users/2")
    .then()
        .spec(getSuccessSpec())
        .body("data.id", equalTo(2));
}

Best Practices

Complete Test Example

public class UserApiTest {

    private static RequestSpecification requestSpec;

    @BeforeClass
    public static void setup() {
        requestSpec = new RequestSpecBuilder()
            .setBaseUri("https://reqres.in")
            .setBasePath("/api")
            .setContentType(ContentType.JSON)
            .log(LogDetail.URI)
            .build();
    }

    @Test
    public void testCreateAndVerifyUser() {
        // Create user
        User newUser = new User("Integration Test", "SDET");

        String userId = given()
            .spec(requestSpec)
            .body(newUser)
        .when()
            .post("/users")
        .then()
            .statusCode(201)
            .body("name", equalTo(newUser.getName()))
            .extract()
            .path("id");

        Assert.assertNotNull(userId, "User ID should not be null");
    }

    @Test
    public void testGetNonExistentUser() {
        given()
            .spec(requestSpec)
        .when()
            .get("/users/999")
        .then()
            .statusCode(404);
    }
}