REST Assured interview question
How do you use JSON schema validation, filters and logging in a REST Assured framework?
Short answer
Use the json-schema-validator module's matchesJsonSchemaInClasspath to assert the response contract, kept in sync with the OpenAPI spec. Use filters (implementing Filter) for cross-cutting concerns: auth token injection and refresh, request/response logging on failure, correlation ids, and attaching traffic to reports.
Answer
These three features are what turn a pile of REST Assured tests into a framework that is easy to debug in CI.
JSON Schema validation
Add the io.rest-assured:json-schema-validator module (same version as REST Assured). Store schemas under src/test/resources/schemas.
import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
given().spec(spec)
.when().get("/orders/{id}", orderId)
.then()
.statusCode(200)
.body(matchesJsonSchemaInClasspath("schemas/order.json"));
A schema is only as useful as its strictness:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": ["id", "status", "total", "lines"],
"additionalProperties": false,
"properties": {
"id": { "type": "string", "pattern": "^[0-9a-f-]{36}$" },
"status": { "enum": ["OPEN", "PAID", "SHIPPED", "CANCELLED"] },
"total": { "type": "number", "minimum": 0 },
"lines": { "type": "array", "minItems": 1 }
}
}
- Mark required fields, or the schema passes an empty object.
additionalProperties: falsecatches unexpected fields (including accidental data exposure) but breaks on harmless additions; decide per API.- The module is built on an older validator that implements JSON Schema draft-04 (and draft-03), so write schemas in draft-04 style. If you need newer drafts, validate the extracted body with a separate library such as networknt’s
json-schema-validator. - Do not hand-maintain schemas that already exist in the OpenAPI spec. Extract or generate them from the spec in the build, or validate against the spec directly with a library such as Atlassian’s
swagger-request-validator, which has a REST Assured filter.
Schema validation checks the provider against its own documented shape. It complements, but does not replace, value assertions and consumer contract tests.
Filters
A filter intercepts every request and response, like servlet middleware:
import io.restassured.filter.Filter;
import io.restassured.filter.FilterContext;
import io.restassured.response.Response;
import io.restassured.specification.FilterableRequestSpecification;
import io.restassured.specification.FilterableResponseSpecification;
public class AuthFilter implements Filter {
private final TokenProvider tokens;
public AuthFilter(TokenProvider tokens) { this.tokens = tokens; }
@Override
public Response filter(FilterableRequestSpecification req,
FilterableResponseSpecification res,
FilterContext ctx) {
req.header("Authorization", "Bearer " + tokens.current());
req.header("X-Correlation-Id", java.util.UUID.randomUUID().toString());
Response response = ctx.next(req, res);
if (response.statusCode() == 401 && tokens.refresh()) {
req.removeHeader("Authorization");
req.header("Authorization", "Bearer " + tokens.current());
response = ctx.next(req, res);
}
return response;
}
}
Register it once in the RequestSpecBuilder with addFilter(new AuthFilter(tokens)). Typical filters:
- Auth injection and refresh, so tests never handle tokens.
- Correlation ids, so a failing test can be traced in service logs.
- Reporting:
io.qameta.allure.restassured.AllureRestAssuredattaches every request and response to the Allure report. - Contract validation against OpenAPI, as above.
Tests that check authentication itself must bypass the auth filter, so build a separate unauthenticated spec for them.
Logging that helps rather than floods
given().log().ifValidationFails()/then().log().ifValidationFails(), orenableLoggingOfRequestAndResponseIfValidationFails()on the config, prints traffic only for failing tests.RequestLoggingFilterandResponseLoggingFiltercan write to aPrintStream. In parallel runs, writing to a sharedSystem.outinterleaves output from different tests, so prefer per-test capture (for example the Allure filter) over console logs.- Mask secrets:
LogConfig.blacklistHeader("Authorization", "Cookie")replaces those header values in logs. Mask sensitive body fields in custom filters.
What interviewers look for
- Correct schema validation setup and a view on schema strictness and OpenAPI sync.
- Writing a custom Filter with ctx.next and using it for cross-cutting concerns.
- Logging only on failure, masking secrets, and parallel-safe reporting.
- Understanding where schema validation stops and contract testing begins.
A strong answer covers
- Schema validation with the json-schema-validator module and matchesJsonSchemaInClasspath
- Keeping schemas strict enough (required, additionalProperties) and in sync with OpenAPI
- Custom Filter for cross-cutting concerns like auth or correlation ids
- Logging only on failure and masking secrets
- Attaching request/response to reports (Allure filter) and thread safety