assert_
glossary ↓ downloads
track: java · selenium
suite 06 · api automation

Chaining requests — real API flows

API automation15 min
as a manual tester

Your E2E case: create a record, then verify it appears in the list, then clean it up.

in automation

Real API testing chains calls the same way: POST to create, extract the new id from the response, GET with that id to verify.

Single-call tests check endpoints; chained tests check the system: does what I created actually exist? The key skill is extracting a value from one response to use in the next request.

CreatePostTest.java — POST, extract, reuse
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

public class CreatePostTest {

    @Test
    void createThenInspect() {
        String newPost = """
            { "title": "Found by automation",
              "body":  "assert_ was here",
              "userId": 7 }
            """;                                  // Java text block — handy for JSON

        int newId =
        given()
            .baseUri("https://jsonplaceholder.typicode.com")
            .header("Content-Type", "application/json")
            .body(newPost)
        .when()
            .post("/posts")
        .then()
            .statusCode(201)                       // 201 = Created
            .body("title", equalTo("Found by automation"))
            .extract().path("id");                 // pull the id out

        System.out.println("Server assigned id: " + newId);
    }
}
predict: what does this print? think it through, then reveal
output
[INFO] Running CreatePostTest
Server assigned id: 101
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

extract().path("id") is the hinge: the response's id becomes a Java variable, ready for the next call — get("/posts/" + newId). That variable-passing between calls is 90% of "advanced" API automation.

Honesty about the practice API: JSONPlaceholder fakes writes — it returns a realistic 201 with id 101, but doesn't persist, so a follow-up GET /posts/101 404s. Perfect for practicing the mechanics; on your real app's API the chain completes: POST → GET verifies → DELETE cleans up. That full loop is the pattern for using APIs to set up UI tests too — create test data through the API in seconds instead of clicking through forms.

The other verbs, quickly

update and delete
.when().put("/posts/1")      // full replace  — expect 200
.when().patch("/posts/1")    // partial update — expect 200
.when().delete("/posts/1")   // remove         — expect 200/204
⚠ when it breaks — the classics
extract().path() hands me null
java.lang.NullPointerException … (or the printed id is null)

Fix: The JSON path doesn't exist in the response — field names are case-sensitive (userId, not userid). Print the whole body with .log().all() and read the real structure.

Weird ClassCastException on an extracted value
java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String

Fix: path() returns typed values: JSON numbers come back as Integer. Receive it as int id = …, or use extract().jsonPath().getString("id") when you truly want text.

⚡ exercise · full CRUD sweep

One test class, four tests against /posts:

  1. Create: POST as above, assert 201 and echo of your title.
  2. Read: GET /posts/1, assert userId equals 1.
  3. Update: PATCH /posts/1 with body {"title":"patched"}, assert 200 and the new title in the response.
  4. Delete: DELETE /posts/1, assert the status. Then print it — is it 200 or 204? APIs vary; knowing to check is the skill.
key takeaways
  • Chaining = extract a value from response N, use it in request N+1.
  • POST expects 201; the created id comes from extract().path("id").
  • APIs are also your fastest way to create test data for UI tests.
← Your first API test — REST Assured Suite test →