Q11 of 40 · REST Assured
How does ResponseSpecBuilder work? When do you use it over inline assertions?
Short answer
Short answer: ResponseSpecBuilder defines a reusable response contract — expected status codes, content type, max response time, invariant body fields — built once and shared via .then(responseSpec). Use it for assertions every endpoint must satisfy; keep per-test-specific assertions inline alongside the shared spec.
Detail
Just as RequestSpecBuilder centralises request setup, ResponseSpecBuilder centralises response expectations that apply across many tests:
ResponseSpecification baseResSpec = new ResponseSpecBuilder()
.expectStatusCode(anyOf(is(200), is(201)))
.expectContentType(ContentType.JSON)
.expectResponseTime(lessThan(2000L), MILLISECONDS)
.build();
Pass it to .then(baseResSpec) and add per-test assertions on top:
given(reqSpec).when().get("/users/1")
.then()
.spec(baseResSpec) // shared invariants
.body("id", equalTo(1)) // test-specific
.body("name", equalTo("Alice"));
When to use ResponseSpecBuilder over inline assertions:
- Invariants shared by every endpoint: content-type, SLA (max response time), envelope fields present
- Compliance rules: e.g., every response must have a
requestIdheader
When NOT to use it: for assertions that are specific to one test or one endpoint — those belong inline. Over-engineering a ResponseSpecBuilder with 20 assertions creates a brittle shared contract that breaks unrelated tests.
// EXAMPLE
BaseApiTest.java
public abstract class BaseApiTest {
protected static RequestSpecification reqSpec;
protected static ResponseSpecification resSpec;
@BeforeAll
static void buildSpecs() {
reqSpec = new RequestSpecBuilder()
.setBaseUri(System.getenv("API_BASE_URL"))
.addHeader("Authorization", "Bearer " + getToken())
.setContentType(ContentType.JSON)
.log(LogDetail.ALL)
.build();
resSpec = new ResponseSpecBuilder()
.expectContentType(ContentType.JSON)
.expectResponseTime(lessThan(3000L), MILLISECONDS)
.build();
}
}
class UserApiTest extends BaseApiTest {
@Test
void getUser_matchesSpec() {
given(reqSpec).pathParam("id", 1)
.when().get("/users/{id}")
.then()
.spec(resSpec) // shared contract
.statusCode(200) // test-specific
.body("id", equalTo(1));
}
}