Rest Assured
Rest Assured — Guia passo a passo
Do zero à referência completa: Maven, clients, JSON schemas, WireMock, segurança, OpenAPI e CI — 98 testes.
API · Java 17 · Spring Petclinic RESTO que é Rest Assured?
Rest Assured é uma DSL Java para testar APIs REST. Integra com JUnit 5, matchers Hamcrest, mapeamento POJO via Jackson e relatórios Allure — ideal para testes de contrato e integração.
- Sintaxe estilo BDD:
given()·when()·then() - Extração JsonPath sem mapeamento completo
- Validação de JSON schema via Rest Assured JSON Schema Validator
- Filtros para logging, SLA e captura de rede customizada
Pré-requisitos
- Java 17+
- Docker (recomendado)
- Maven 3.9+
java -version
mvn -version
docker --version
Instalação & primeira execução
git clone https://github.com/lflucasferreira/rest-assured.git
cd rest-assured
# Opção A — Docker (API padrão + API segura + testes)
docker compose up --abort-on-container-exit --exit-code-from tests
# Opção B — Maven local (suba a API antes)
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
Estrutura do projeto
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/ # Cenários de erro parametrizados
└── utils/ # Config, factories, validators
src/test/resources/
├── config/dev.properties # API 9966 + secure 9967
├── config/docker.properties
└── schemas/*.json # owner, pet, visit, vet, openapi, ...
Cobertura da suite (98 testes)
Resumo dos pacotes e clients adicionados na expansão da suite:
| Área | Classes de teste | Endpoints principais |
|---|---|---|
| Owners | OwnersApiTest, OwnersNegativeApiTest, OwnersV2ApiTest | GET/POST/PUT/DELETE /owners, paginação /v2/owners |
| Pets | PetsApiTest, PetsNestedApiTest, PetsNegativeApiTest | /pets, /owners/{id}/pets |
| Visits | VisitsApiTest, VisitsNegativeApiTest | CRUD /visits, POST nested |
| Vets & Specialties | VetsApiTest, SpecialtiesApiTest | CRUD /vets, /specialties |
| Pet types | PetTypesApiTest | CRUD /pettypes |
| Smoke | ActuatorSmokeTest | /actuator/health |
| Segurança | SecurityApiTest, SecurityAuthorizationTest, UsersApiTest | Basic Auth na API :9967 |
| Avançado | OpenApiContractTest, WireMockResilienceTest, PerformanceSmokeTest, … | OpenAPI, SLA, integridade |
Camada de clients de API
Todas as chamadas HTTP passam por classes client. Veja 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");
}
}
Setup BaseTest
@BeforeEach
void setUp() {
RestAssured.requestSpecification = requestSpec;
networkCapture.reset();
}
BaseTest conecta OwnersClient, PetsClient, PetTypesClient, VisitsClient e o filtro de captura de rede.
Asserções & 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()));
Factory de dados de teste
Owner owner = TestDataFactory.buildOwner();
PetFields pet = TestDataFactory.buildPetFields(typeId, typeName);
Owner invalid = TestDataFactory.buildInvalidOwnerWithAlphabeticTelephone();
JavaFaker gera dados únicos; factories negativas codificam payloads inválidos.
Captura de rede
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)));
Cenários adicionais em WireMockResilienceTest (timeout, JSON inválido, connection reset) e WireMockRetryIntegrationTest (retry após 503).
Segurança & RBAC
Docker Compose sobe duas instâncias da API:
- 9966 — sem autenticação (padrão)
- 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 valida 401/200. SecurityAuthorizationTest testa RBAC (VET_ADMIN vs OWNER_ADMIN) quando o login de usuários provisionados está disponível.
OpenAPI & contratos
// Documento completo
openApiClient.getApiDocs(); // GET /v3/api-docs
// Validação por operação
OpenApiResponseValidator.assertResponseMatchesDocumentedOperation(
openApiResponse, apiResponse, "/api/owners", "get");
Schemas em schemas/openapi-docs-schema.json, visit-schema.json, vet-schema.json, specialty-schema.json, owners-page-schema.json.
Testes parametrizados
@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(...);
}
Como executar
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:
- Dois service containers: API padrão (
9966) e API segura (9967) - Health check no Actuator
/actuator/health mvn clean test— 98 testes, gate em todo PR/push paramain- Relatório Allure publicado no GitHub Pages em push para
main
Documentação de treinamento
- Walkthroughs em Português — bloco a bloco por classe
- English walkthroughs
- Slides Reveal.js · PDF
- Perguntas de entrevista (PT)