Contract testing¶
Kappa has first-class support for testing if your API under testing conforms to its defined OpenAPI description. Seamlessly integrates with MockMvc-based SpringBootTests.
Installation¶
Add a contract-driven test¶
openapi: "3.1.0"
info:
title: "Pets API"
version: 0.0.1
paths:
/api/pets:
post:
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/CreatePetRequest"
get:
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Pet"
components:
schemas:
Name:
type: string
minLength: 1
Pet:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: integer
name:
$ref: "#/components/schemas/Name"
owner:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
type: integer
name:
$ref: "#/components/schemas/Name"
birthDate:
type: string
format: date
KappaSpringBootExampleApplication.java:
@SpringBootApplication
public class KappaSpringBootExampleApplication {
public static void main(String[] args) {
SpringApplication.run(KappaSpringBootExampleApplication.class, args);
}
@Bean
public KappaSpringConfiguration kappaConfig() {
var kappaConfig = new KappaSpringConfiguration();
var mapping = new LinkedHashMap<String, String>();
mapping.put("/**", "/openapi/pets-api.yaml"); // (1)
kappaConfig.setOpenapiDescriptions(mapping);
return kappaConfig;
}
}
- If your OpenAPI descriptions are split into multiple files, you can map multiple request paths to yaml files describing them
record User(int id, String firstName, String lastName) {
}
record Pet(int id, String name, User owner, long birthDate) {
}
@RestController
@RequestMapping("/api/pets")
public class PetController {
@GetMapping
List<Pet> getPets() {
return List.of(
new Pet(
1,
"",
new User(2, "John", "Doe"),
LocalDate.parse("2017-08-08").toEpochDay()
)
);
}
}
@SpringBootTest
@AutoConfigureMockMvc
@EnableKappaContractTesting //(1)
public class ContractDrivenApiTest {
@Autowired
MockMvc mvc;
@Test
void testListPets() throws Exception {
mvc.perform(get("/api/pets")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.size()").value(1)); // (2)
}
}
- This annotation enables contract verification on every request and response. If either the request or response doesn't match, the API, the test fails
- The assertions of the test pass, but Kappa will catch the structural mismatches of the response
If you run the above ContractDrivenApiTest, it will fail and report the following errors with the response structure:
- an empty pet name is returned, while it is described as a
minLength: 1string - two undefined properties of the owner are returned:
firstNameandlastName - on the other hand, the mandatory
namefield of the owner is missing
The complete example is available in the Kappa Examples repo.