DEV Community

Jan Mewes
Jan Mewes

Posted on

Spring: Adding OpenAPI validation to MockMVC tests

Motivation

Creating the OpenAPI specification (OAS) before the implementation of the API might lead to a better API design than the generation of the OAS from the implementation, the generations of the OAS from the tests, or not using OAS altogether.

However, this raises the need to validate that the implementation complies with the OAS. This may be done with Atlassian's open-source project swagger-request-validator as described below.

Also see

Overview

swagger-request-validator has a core component and allows integration with different testing approaches with a handful of sub-components. One of those sub-components is swagger-request-validator-mockmvc which integrates with Spring Mock MVC coming from spring-test that it used in the tests of the ksch.patientmanagment.impl project.

swagger-request-validator-core leverages jackson, io.swagger.core and io.swagger.parser to parse the test data and OAS. Then it matches them with the help of java-json-tools and reports violations if they don't match.

Those dependencies are visualized in the following UML Component diagram:

Component diagram

Implementation details

The swagger-request-validator library can be included by declaring the following dependencies in the build.gradle file:

dependencies {
  testImplementation('com.atlassian.oai:swagger-request-validator-core:2.34.1')
  testImplementation('com.atlassian.oai:swagger-request-validator-mockmvc:2.34.1')
}
Enter fullscreen mode Exit fullscreen mode

To allow the usage of the allOf feature of OAS, the withResolveCombinators option of OpenApiInteractionValidator needs to be set to true (see swagger-request-validator#315) and additional properties need to be ignored.

public static OpenApiInteractionValidator createValidator(String specificationUrl) {
    LevelResolver levelResolver = LevelResolver.create()
        .withLevel("validation.schema.additionalProperties", ValidationReport.Level.IGNORE)
        .build();
    ParseOptions parseOptions = new ParseOptions();

    parseOptions.setResolve(true);
    parseOptions.setResolveFully(false);
    parseOptions.setResolveCombinators(true);

    return OpenApiInteractionValidator
        .createForSpecificationUrl(specificationUrl)
        .withLevelResolver(levelResolver)
        .withParseOptions(parseOptions)
        .build();
}
Enter fullscreen mode Exit fullscreen mode

Then the openApi() validation can be added to the MockMVC expectations in the test.

OpenApiInteractionValidator validator = OasValidatorFactory.createValidator(
        "../../docs/openapi.yml"
);

mockMvc.perform(post("/api/patients").accept(APPLICATION_JSON))
        .andDo(print())
        .andExpect(status().isOk())
        .andExpect(jsonPath("_id", is(notNullValue())))
        .andExpect(openApi().isValid(validator))
;
Enter fullscreen mode Exit fullscreen mode

References

Top comments (0)