Manually: send request in Postman, eyeball the JSON, judge pass/fail.
REST Assured writes that as given/when/then — and its syntax literally reads like a test case.
REST Assured is Java's standard API-testing library. Add it to pom.xml — and note the official quirk: declare it before the JUnit dependency so the right Hamcrest version wins:
<dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <version>6.0.0</version> <scope>test</scope> </dependency>
import org.junit.jupiter.api.Test; import static io.restassured.RestAssured.*; import static org.hamcrest.Matchers.*; public class UserApiTest { @Test void userOneIsLeanne() { given() .baseUri("https://jsonplaceholder.typicode.com") .when() .get("/users/1") .then() .statusCode(200) .body("name", equalTo("Leanne Graham")) .body("address.city", equalTo("Gwenborough")) // the dot path! .body("company.name", containsString("Romaguera")); } }
[INFO] Running UserApiTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] Time elapsed: 1.2 s ← no browser. feel the speed.
[INFO] BUILD SUCCESSgiven (setup) / when (the action) / then (assertions) — preconditions, steps, expected results. Your test case template became a syntax.
.body("name", equalTo("Leanne Graham")) .body("email", containsString("@")) .body("id", greaterThan(0)) .body("$", hasSize(10)) // $ = whole response; size of an array .body("title", notNullValue())
java.lang.AssertionError: 1 expectation failed. JSON path name doesn't match. Expected: Leanne Graham Actual: Ervin Howell
Expected vs actual, with the JSON path named — the same failure anatomy you've read since Suite 01, minus screenshots because there's nothing to photograph. For debugging, add .log().all() after then() to print the entire request and response.
Fix: The classic ordering bug: rest-assured must be declared before junit-jupiter in pom.xml so the right Hamcrest wins. Reorder, reload Maven.
Fix: Usually a missing leading slash or a pluralization typo: get("users/1") vs get("/users/1"), /user/1 vs /users/1. Add .log().all() after then() to see the exact URL that was called.
Write CommentsApiTest against /posts/1/comments:
"$", hasSize(5))."[0].email") contains "@"./posts/99999 returns 404. Your first API boundary test.