Appearance
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/thenstyle. - 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 arraySending 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 | |
|---|---|---|
| Boilerplate | more (build request, parse, assert) | minimal, fluent |
| Assertions | your choice (AssertJ) | built-in + Hamcrest/JSON-path |
| Dependency | JDK only | extra test dependency |
| Best for | production code, full control | concise 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
RequestSpecificationto keep tests focused on behavior. - Assert on meaningful body fields, not just the status code.
Lesson Quiz
In RestAssured, what does the when() block do?
The string in .body("items[0].name", equalTo("x")) is…
Why is asserting only statusCode(200) often insufficient?
How do you continue a test with AssertJ on the response object?
What's a reason to choose RestAssured over raw HttpClient for a test suite?
Next: Mocking Services with WireMock. This module's lab is in labs/src/main/java/com/jse21/m17_api/.