Rest Assured
Rest Assured — Step-by-step guide
From zero to full reference: Maven setup, client layer, JSON schemas, security, OpenAPI, and CI — 98 tests.
API · Java 17 · Spring Petclinic RESTWhat is Rest Assured?
Rest Assured is a Java DSL for testing REST APIs. It integrates with JUnit 5, Hamcrest matchers, Jackson POJO mapping, and Allure reporting — ideal for contract and integration tests.
- BDD-style syntax:
given()·when()·then() - JsonPath extraction without full object mapping
- JSON schema validation via Rest Assured JSON Schema Validator
- Filters for logging, SLA checks, and custom network capture
Prerequisites
- Java 17+
- Docker (recommended)
- Maven 3.9+
java -version
mvn -version
docker --version
Installation & first run
git clone https://github.com/lflucasferreira/rest-assured.git
cd rest-assured
# Option A — Docker (default API + secure API + tests)
docker compose up --abort-on-container-exit --exit-code-from tests
# Option B — local Maven (start API first)
docker run -p 9966:9966 springcommunity/spring-petclinic-rest:latest
docker run -p 9967:9966 -e PETCLINIC_SECURITY_ENABLE=true springcommunity/spring-petclinic-rest:latest
mvn clean test
Project structure
src/test/java/com/portfolio/petclinic/
├── base/BaseTest.java
├── clients/ # Actuator, Owners, Pets, Visits, Vets, ...
├── models/ # POJOs + User, Vet, Specialty
├── tests/
│ ├── smoke/ # ActuatorSmokeTest
│ ├── security/ # Basic Auth, RBAC, Users
│ ├── advanced/ # WireMock, OpenAPI, performance
│ ├── flows/ # PetLifecycleFlowTest
│ └── negative/ # Parameterized error paths
└── utils/ # Config, factories, validators
src/test/resources/
├── config/dev.properties # API 9966 + secure 9967
├── config/docker.properties
└── schemas/*.json # owner, pet, visit, vet, openapi, ...
Suite coverage (98 tests)
Summary of packages and clients added in the expanded suite:
| Area | Test classes | Main endpoints |
|---|---|---|
| Owners | OwnersApiTest, OwnersNegativeApiTest, OwnersV2ApiTest | GET/POST/PUT/DELETE /owners, pagination /v2/owners |
| Pets | PetsApiTest, PetsNestedApiTest, PetsNegativeApiTest | /pets, /owners/{id}/pets |
| Visits | VisitsApiTest, VisitsNegativeApiTest | CRUD /visits, nested POST |
| Vets & Specialties | VetsApiTest, SpecialtiesApiTest | CRUD /vets, /specialties |
| Pet types | PetTypesApiTest | CRUD /pettypes |
| Smoke | ActuatorSmokeTest | /actuator/health |
| Security | SecurityApiTest, SecurityAuthorizationTest, UsersApiTest | Basic Auth on API :9967 |
| Advanced | OpenApiContractTest, WireMockResilienceTest, PerformanceSmokeTest, … | OpenAPI, SLA, integrity |
API client layer
All HTTP calls go through client classes. See api-testing-strategy.md.
public class OwnersClient extends ApiClient {
public Response getAllOwners() {
return given().spec(requestSpec).when().get("/owners");
}
public Response createOwner(Owner owner) {
return given().spec(requestSpec).body(owner).when().post("/owners");
}
}
BaseTest setup
@BeforeEach
void setUp() {
RestAssured.requestSpecification = requestSpec;
networkCapture.reset();
}
BaseTest wires OwnersClient, PetsClient, PetTypesClient, VisitsClient, and the network capture filter.
Assertions & JSON schemas
ResponseValidator.assertStatusCode(response.getStatusCode(), 201);
ResponseValidator.assertMatchesSchema(body, "schemas/owner-schema.json");
Owner owner = response.as(Owner.class);
assertThat(owner.getFirstName(), is(payload.getFirstName()));
Test data factory
Owner owner = TestDataFactory.buildOwner();
PetFields pet = TestDataFactory.buildPetFields(typeId, typeName);
Owner invalid = TestDataFactory.buildInvalidOwnerWithAlphabeticTelephone();
JavaFaker generates unique data; negative factories encode invalid payloads.
Network capture
NetworkInspector.attachLastExchangeToAllure(networkCapture);
NetworkInspector.assertLastRequestUriContains(networkCapture, "/pets");
NetworkInspector.assertResponseSequenceContains(networkCapture, "/owners", "/pets/");
WireMock
wireMockSupport.server().stubFor(post(urlEqualTo("/audit/owner-created"))
.willReturn(aResponse().withStatus(202)));
WireMock.verify(postRequestedFor(urlEqualTo("/audit/owner-created"))
.withRequestBody(equalToJson(expectedJson, true, true)));
Additional scenarios in WireMockResilienceTest (timeout, invalid JSON, connection reset) and WireMockRetryIntegrationTest (retry after 503).
Security & RBAC
Docker Compose runs two API instances:
- 9966 — no authentication (default)
- 9967 —
PETCLINIC_SECURITY_ENABLE=true, Basic Authadmin:admin
OwnersClient.secured().getAllOwners();
OwnersClient.withCredentials("admin", "admin").createOwner(payload);
UsersClient.secured().createUser(TestDataFactory.buildUniqueSecureUser("OWNER_ADMIN"));
SecurityApiTest validates 401/200. SecurityAuthorizationTest exercises RBAC (VET_ADMIN vs OWNER_ADMIN) when provisioned-user login is available.
OpenAPI & contracts
openApiClient.getApiDocs(); // GET /v3/api-docs
OpenApiResponseValidator.assertResponseMatchesDocumentedOperation(
openApiResponse, apiResponse, "/api/owners", "get");
Schemas: openapi-docs-schema.json, visit-schema.json, vet-schema.json, specialty-schema.json, owners-page-schema.json.
Parameterized tests
@ParameterizedTest(name = "GET /owners/{0} should return {1}")
@CsvSource({ "99999, 404", "0, 404" })
void shouldReturnExpectedStatusForInvalidOwnerIds(int ownerId, int expectedStatus) {
Response response = ownersClient.getOwnerById(ownerId);
ErrorResponseValidator.assertErrorStatusAndOptionalProblemDetail(...);
}
How to run
mvn clean test
mvn test -Dtest=VisitsApiTest
mvn test -Denv=dev -Dapi.base.uri=http://localhost:9966/petclinic/api \
-Dapi.secure.base.uri=http://localhost:9967/petclinic/api
mvn test -Dtest.groups=smoke
mvn allure:serve
CI — GitHub Actions
Workflow .github/workflows/api-tests.yml:
- Two service containers: default API (
9966) and secure API (9967) - Health check on Actuator
/actuator/health mvn clean test— 98 tests, gate on every PR/push tomain- Allure report published to GitHub Pages on push to
main
Training documentation
- English walkthroughs — block-by-block per test class
- Walkthroughs em Português
- Reveal.js slides · PDF
- Interview questions (PT)