Q14 of 40 · REST Assured
How would you write a generic helper that accepts a path and returns a typed response?
REST AssuredMidrest-assuredgenericstyperefapi-clientdesign-pattern
Short answer
Short answer: Define a method that accepts a String path and a TypeRef<T> and calls extract().as(typeRef). The caller passes new TypeRef<User>(){} or new TypeRef<List<Order>>(){} at the call site — Jackson resolves the type token at runtime. This eliminates unchecked casts and gives compile-time safety on the return type.
Detail
A typed helper wraps the REST Assured chain so callers work with typed objects rather than raw responses:
public <T> T get(String path, TypeRef<T> type) {
return given(reqSpec)
.when().get(path)
.then().statusCode(200)
.extract().as(type);
}
Callers:
User user = apiClient.get("/users/1", new TypeRef<User>() {});
List<User> list = apiClient.get("/users", new TypeRef<List<User>>() {});
Extending the pattern — accept expected status code too:
public <T> T request(Method method, String path, Object body,
int expectedStatus, TypeRef<T> type) {
return given(reqSpec)
.body(body)
.when().request(method, path)
.then().statusCode(expectedStatus)
.extract().as(type);
}
This service-layer pattern hides REST Assured behind an interface — if you ever swap the HTTP library, only this class changes.
// EXAMPLE
ApiClient.java
public class ApiClient {
private final RequestSpecification spec;
public ApiClient(RequestSpecification spec) { this.spec = spec; }
public <T> T get(String path, TypeRef<T> type) {
return given(spec)
.when().get(path)
.then().statusCode(200)
.extract().as(type);
}
public <T> T post(String path, Object body, int expectedStatus, TypeRef<T> type) {
return given(spec)
.body(body)
.when().post(path)
.then().statusCode(expectedStatus)
.extract().as(type);
}
}
// Usage in test
User created = client.post("/users",
Map.of("name", "Alice", "email", "alice@example.com"),
201, new TypeRef<User>() {});
assertThat(created.getId()).isPositive();// WHAT INTERVIEWERS LOOK FOR
Use of TypeRef (not raw Class<T>) to preserve generic type information, and the service-layer abstraction that hides REST Assured behind an API. This is a mid-to-senior pattern that shows awareness of maintainability beyond individual tests.
// COMMON PITFALL
Using Class<T> instead of TypeRef<T> — this works for non-generic types (User.class) but fails at runtime for List<User> because type erasure makes the element type unknown to Jackson.