Skip to content
Spring Boot sb testing 2 min read

REST Assured

REST Assured is a Java DSL for testing HTTP APIs that reads like the behavior it describes: given some request setup, when you call an endpoint, then assert the response. It sends real HTTP requests, so it pairs naturally with @SpringBootTest(RANDOM_PORT) for expressive end-to-end API tests.

Dependency

REST Assured is not part of spring-boot-starter-test, so add it explicitly with test scope.

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <scope>test</scope>
</dependency>

Note: Spring Boot manages the REST Assured version in its dependency BOM, so you can omit the <version> — the curated version is wired in automatically.

Pointing REST Assured at the running app

Start the server on a random port, then tell REST Assured the port in @BeforeEach.

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

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class ProductApiRestAssuredTest {

    @LocalServerPort
    int port;

    @BeforeEach
    void setUp() {
        RestAssured.baseURI = "http://localhost";
        RestAssured.port = port;
    }
}

The given/when/then DSL

Each test reads top to bottom: configure the request, fire it, assert the response.

@Test
void returnsProductById() {
    given()
        .accept(ContentType.JSON)
    .when()
        .get("/api/products/1")
    .then()
        .statusCode(200)
        .body("name", equalTo("Keyboard"))
        .body("price", equalTo(49.90f));
}

Output:

ProductApiRestAssuredTest > returnsProductById() PASSED

POSTing a JSON body

Set the content type and pass a payload — REST Assured serializes objects with Jackson.

@Test
void createsProduct() {
    given()
        .contentType(ContentType.JSON)
        .body("""
            { "name": "Mouse", "price": 19.90 }
            """)
    .when()
        .post("/api/products")
    .then()
        .statusCode(201)
        .header("Location", containsString("/api/products/"))
        .body("id", notNullValue())
        .body("name", equalTo("Mouse"));
}

Body and jsonPath assertions

The body(...) matchers use a GPath/JsonPath-style expression and Hamcrest matchers. They handle nested fields and collections cleanly.

@Test
void listReturnsAllProducts() {
    given()
    .when()
        .get("/api/products")
    .then()
        .statusCode(200)
        .body("size()", equalTo(2))
        .body("name", hasItems("Keyboard", "Mouse"))
        .body("[0].price", greaterThan(0f));
}

To pull a value out of the response for further assertions, extract it:

long id = given()
        .contentType(ContentType.JSON)
        .body(new ProductRequest("Pad", new BigDecimal("9.90")))
    .when()
        .post("/api/products")
    .then()
        .statusCode(201)
        .extract().jsonPath().getLong("id");

assertThat(id).isPositive();

Sending auth headers

Attach bearer tokens, basic auth, or custom headers in the given() block — exactly what you need for secured endpoints.

@Test
void rejectsRequestWithoutToken() {
    given()
    .when()
        .get("/api/admin/users")
    .then()
        .statusCode(401);
}

@Test
void allowsRequestWithToken() {
    given()
        .header("Authorization", "Bearer " + validJwt)
    .when()
        .get("/api/admin/users")
    .then()
        .statusCode(200);

    // Built-in auth helpers also exist:
    given().auth().preemptive().basic("admin", "secret");
    given().auth().oauth2(validJwt);
}

REST Assured vs MockMvc / TestRestTemplate

All three test HTTP endpoints, but at different levels and with different ergonomics.

ToolReal HTTP?StyleBest for
MockMvc (@WebMvcTest)No (mock servlet)perform().andExpect()Fast controller slice tests
TestRestTemplateYes (RANDOM_PORT)Imperative, returns ResponseEntityPlain integration tests
REST AssuredYes (RANDOM_PORT)Fluent given/when/thenReadable end-to-end API specs

Tip: Use RestAssured.enableLoggingOfRequestAndResponseIfValidationFails() once in setup so failing tests print the full request and response — it turns a cryptic matcher failure into an obvious diagnosis.

Warning: REST Assured drives the API over the network, so it is slower than MockMvc. Keep the bulk of your controller coverage in @WebMvcTest and use REST Assured for a focused set of full-stack acceptance tests.

Last updated June 13, 2026
Was this helpful?