Skip to content

Lesson 03 · REST Testing with RestAssured

Beyond the 1Z0-830 exam

You can test APIs with HttpClient + Jackson + assertions (the lab does). But for test suites, RestAssured packages request-building, JSON parsing, and assertions into one fluent, BDD-flavoured DSL — far less boilerplate per test.

Objectives

After this lesson you will be able to:

  • Write a REST test in the given / when / then style.
  • Assert on status code, body, and headers.
  • Extract and assert values with JSON-path.
  • Send bodies and parameters, and extract a response for further checks.

given / when / then

RestAssured reads like a sentence: arrange the request, perform it, assert the response.

java
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

given()
    .baseUri("https://api.example.com")
    .header("Accept", "application/json")
.when()
    .get("/widgets/1")
.then()
    .statusCode(200)
    .body("name", equalTo("Gizmo"))
    .body("inStock", is(true));
  • given() — set up headers, query/path params, auth, request body.
  • when() — issue the verb (get, post, put, delete).
  • then() — assert on the response using Hamcrest matchers.

JSON-path assertions

The string in .body("...", matcher) is a JSON-path into the response. RestAssured parses the body for you — no manual ObjectMapper:

java
.then()
    .body("id", equalTo(1))                          // top-level field
    .body("tags", hasItems("a", "b"))                // array contents
    .body("items.size()", equalTo(3))                // array length
    .body("items[0].name", equalTo("first"))         // nested index
    .body("items.name", hasItem("Gizmo"));           // collect a field across the array

Sending data

java
given()
    .contentType(ContentType.JSON)
    .body(new Widget(0, "Gizmo", true))              // serialized for you (Jackson/Gson on classpath)
    .queryParam("notify", true)
.when()
    .post("/widgets")
.then()
    .statusCode(201)
    .header("Location", containsString("/widgets/"));

Extracting for richer assertions

When Hamcrest isn't enough, extract and assert with AssertJ (Module 14):

java
Widget created = given().contentType(ContentType.JSON).body(input)
    .when().post("/widgets")
    .then().statusCode(201)
    .extract().as(Widget.class);                     // deserialize the response

assertThat(created.id()).isPositive();

SDET note

Keep a shared RequestSpecification (base URI, auth, default headers) so individual tests stay about behavior, not setup. Reusing one spec is the API-test analogue of the Page Object Model you'll meet in Module 18 — push boilerplate out of the test body.

Gotcha — don't only assert status

A 200 OK with the wrong body still passes a status-only check. Assert on the fields that matter (IDs, key values, error codes in the body), not just the HTTP status — that's where real regressions hide.

RestAssured vs the raw client

HttpClient + Jackson (the lab)RestAssured
Boilerplatemore (build request, parse, assert)minimal, fluent
Assertionsyour choice (AssertJ)built-in + Hamcrest/JSON-path
DependencyJDK onlyextra test dependency
Best forproduction code, full controlconcise API test suites

The lab uses the raw client to stay green-by-default; in a real test module you'd reach for RestAssured.

Key Takeaways

  • RestAssured structures a test as given (arrange) → when (act) → then (assert).
  • Assert status, headers, and body; the body uses JSON-path with Hamcrest matchers.
  • Extract the response (.extract().as(Type.class)) to continue with AssertJ.
  • Share a RequestSpecification to keep tests focused on behavior.
  • Assert on meaningful body fields, not just the status code.

Lesson Quiz

Lesson Quiz · RestAssured0 / 5
  1. In RestAssured, what does the when() block do?

    • ASets up headers and body
    • BIssues the HTTP request (get/post/…)
    • CAsserts the response
    • DStarts a mock server
  2. The string in .body("items[0].name", equalTo("x")) is…

    • AA regex
    • BA JSON-path into the response body
    • CAn XPath
    • DA SQL fragment
  3. Why is asserting only statusCode(200) often insufficient?

    • A200 is never returned
    • BA 200 with a wrong/empty body still passes — assert the meaningful body fields too
    • CStatus codes are unreliable
    • DIt throws an exception
  4. How do you continue a test with AssertJ on the response object?

    • AYou can't
    • BUse .extract().as(Type.class) to deserialize, then assertThat(...)
    • CCall ObjectMapper manually inside then()
    • DReturn the raw String only
  5. What's a reason to choose RestAssured over raw HttpClient for a test suite?

    • AIt's part of the JDK
    • BFar less boilerplate — fluent request building, JSON parsing, and assertions in one DSL
    • CIt's faster at runtime
    • DIt avoids needing any assertions

Next: Mocking Services with WireMock. This module's lab is in labs/src/main/java/com/jse21/m17_api/.