Q26 of 40 · REST Assured
How would you build a REST Assured framework from scratch for a 100-engineer team?
Short answer
Short answer: Layer a BaseApiTest with RequestSpecBuilder and ResponseSpecBuilder, env-config loaded from properties or a config library, a token-refresh helper, and an Allure filter for reporting. Wrap REST Assured in a service layer so test methods call service.getUser(id) rather than fluent chains — the framework is the service layer, not the raw DSL.
Detail
A framework at scale needs four layers:
1. Configuration: load baseUri, credentials, and timeouts from environment variables or a config library (Owner, Typesafe Config). Never hard-code. Resolve at @BeforeAll and inject into specs.
2. Spec builders (BaseApiTest): RequestSpecification with shared headers, auth, content type, logging filter. ResponseSpecification with content-type and SLA assertions. Built once per suite, never per test.
3. Service layer — hide REST Assured behind typed methods:
public class UserService {
private final ApiClient client;
public User createUser(CreateUserRequest req) { ... }
public User getUser(int id) { ... }
public void deleteUser(int id) { ... }
}
Test code calls userService.createUser(req) — if you later swap REST Assured for another library, only this layer changes.
4. Reporting: register AllureRestAssured as a filter in RequestSpecBuilder so every request/response appears as an attachment on the Allure step. Annotate test methods with @Feature, @Story, @Severity.
Team scale concerns: enforce the BaseApiTest contract in code review, use Checkstyle/ArchUnit to prevent direct RestAssured.* static calls outside the service layer, and provide a starter module with examples.
// EXAMPLE
FrameworkOverview.java
// Config layer
public class ApiConfig {
private static final Config cfg = ConfigFactory.create(Config.class);
interface Config { String apiBaseUrl(); String apiToken(); }
public static String baseUrl() { return cfg.apiBaseUrl(); }
public static String token() { return cfg.apiToken(); }
}
// Base test layer
public abstract class BaseApiTest {
protected static RequestSpecification reqSpec;
protected static ResponseSpecification resSpec;
@BeforeAll static void init() {
reqSpec = new RequestSpecBuilder()
.setBaseUri(ApiConfig.baseUrl())
.addHeader("Authorization", "Bearer " + ApiConfig.token())
.setContentType(ContentType.JSON)
.addFilter(new AllureRestAssured())
.log(LogDetail.ALL)
.build();
resSpec = new ResponseSpecBuilder()
.expectContentType(ContentType.JSON)
.expectResponseTime(lessThan(3000L), MILLISECONDS)
.build();
}
}
// Service layer
public class UserService {
private final RequestSpecification spec;
public UserService(RequestSpecification spec) { this.spec = spec; }
public User createUser(Map<String, Object> body) {
return given(spec).body(body)
.when().post("/users")
.then().spec(resSpec).statusCode(201)
.extract().as(User.class);
}
}
// Test — no REST Assured in sight
class UserApiTest extends BaseApiTest {
private UserService users;
@BeforeEach void setup() { users = new UserService(reqSpec); }
@Test void createUser_returnsUser() {
User u = users.createUser(Map.of("name", "Alice", "email", "a@b.com"));
assertThat(u.getId()).isPositive();
}
}