REST Assured — Java API Testing
REST Assured is the most popular Java library for testing REST APIs. It provides a fluent, BDD-style DSL that makes API tests extraordinarily readable. REST Assured integrates seamlessly with TestNG, JUnit, and Maven — making it the default choice for every Java SDET working in enterprise environments with Spring Boot microservices.
REST Assured Comprehensive Test Examples
// ══════════════════════════════════════════════════════════════
// pom.xml dependency:
// <dependency>
// <groupId>io.rest-assured</groupId>
// <artifactId>rest-assured</artifactId>
// <version>5.4.0</version>
// </dependency>
// ══════════════════════════════════════════════════════════════
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import org.testng.annotations.*;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class UserApiTest {
private String authToken;
private int userId;
@BeforeClass
public void setup() {
RestAssured.baseURI = "https://staging.myapp.com";
RestAssured.basePath = "/api";
// Login and extract token (request chaining)
authToken = given()
.contentType("application/json")
.body("{ \"email\": \"admin@test.com\", \"password\": \"Admin@1234\" }")
.when()
.post("/auth/login")
.then()
.statusCode(200)
.extract().path("token");
}
@Test(description = "GET: Retrieve user by ID")
public void getUserById_ShouldReturn200WithCorrectData() {
given()
.header("Authorization", "Bearer " + authToken)
.when()
.get("/users/123")
.then()
.statusCode(200)
.contentType("application/json")
.body("id", equalTo(123))
.body("email", matchesPattern("[a-z]+@[a-z]+\\.[a-z]+"))
.body("name", not(emptyString()))
.body("$", not(hasKey("password"))) // Security: no password exposed
.time(lessThan(500L)); // Performance: under 500ms
}
@Test(description = "POST: Create a new user")
public void createUser_ShouldReturn201WithUserId() {
long timestamp = System.currentTimeMillis();
String body = String.format(
"{\"name\": \"Test User\", \"email\": \"test%d@test.com\"}", timestamp
);
userId = given()
.header("Authorization", "Bearer " + authToken)
.contentType("application/json")
.body(body)
.when()
.post("/users")
.then()
.statusCode(201)
.body("id", greaterThan(0))
.body("email", containsString("@test.com"))
.extract().path("id");
}
@Test(description = "GET: 404 for non-existent user")
public void getUserById_WhenNotFound_ShouldReturn404() {
given()
.header("Authorization", "Bearer " + authToken)
.when()
.get("/users/99999")
.then()
.statusCode(404)
.body("error", containsString("not found"))
.body("$", not(hasKey("stackTrace"))); // No stack trace exposed
}
@Test(description = "GET: 401 for unauthenticated request")
public void getUser_WithoutAuth_ShouldReturn401() {
when()
.get("/users/123") // No auth header
.then()
.statusCode(401)
.body("error", containsString("Authentication required"));
}
@Test(description = "PATCH: Update user name")
public void updateUserName_ShouldReturn200WithUpdatedData() {
given()
.header("Authorization", "Bearer " + authToken)
.contentType("application/json")
.body("{\"name\": \"Updated Name\"}")
.when()
.patch("/users/" + userId)
.then()
.statusCode(200)
.body("name", equalTo("Updated Name"));
}
@Test(description = "DELETE: Remove user")
public void deleteUser_ShouldReturn204() {
given()
.header("Authorization", "Bearer " + authToken)
.when()
.delete("/users/" + userId)
.then()
.statusCode(204);
// Verify deletion — GET should now return 404
given()
.header("Authorization", "Bearer " + authToken)
.when()
.get("/users/" + userId)
.then()
.statusCode(404);
}
}Common Mistakes
- Not using RequestSpecification for shared headers — create a shared spec with log().ifValidationFails() and auth headers to avoid repetition
- Not asserting the full round-trip — create user (POST) → fetch user (GET) → verify data matches → update (PATCH) → verify update → delete (DELETE) → verify gone
- Ignoring negative paths in REST Assured — easy to only write happy-path tests; always add 401, 403, 404, 400 tests
- Hardcoding user IDs — use @BeforeMethod to create test data via API and capture IDs; hardcoded IDs break when test database is reset
Tip
Tip
Practice REST Assured Java API Testing in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
Test happy path + errors. k6 for load.
Practice Task
Note
Practice Task — (1) Write a working example of REST Assured Java API Testing from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Quick Quiz
Common Mistake
Warning
A common mistake with REST Assured Java API Testing is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready software testing code.
Key Takeaways
- REST Assured is the most popular Java library for testing REST APIs.
- Not using RequestSpecification for shared headers — create a shared spec with log().ifValidationFails() and auth headers to avoid repetition
- Not asserting the full round-trip — create user (POST) → fetch user (GET) → verify data matches → update (PATCH) → verify update → delete (DELETE) → verify gone
- Ignoring negative paths in REST Assured — easy to only write happy-path tests; always add 401, 403, 404, 400 tests