Spring: Adding OpenAPI validation to MockMVC tests
Tags: spring, openapi
Published: 2023-05-13 13:54:30

---
title: Spring: Adding OpenAPI validation to MockMVC tests
published: true
description: This blog post describes how OpenAPI specification validation was added to the tests in a Java/Spring project that uses Gradle as build system.
tags: spring, openapi
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-05-13 13:50 +0000
---

## 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][swagger-request-validator] as described below.

**Also see**

- [Using spec-first API development for speed and sanity | atlassian.com](https://www.atlassian.com/blog/technology/spec-first-api-development)
- [Episode 542: Brendan Callum on Contract-Driven APIs | se-radio.net](https://www.se-radio.net/2022/12/episode-542-brendan-callum-on-contract-driven-apis)

## Overview

[swagger-request-validator][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][swagger-request-validator-mockmvc] which integrates with Spring Mock MVC coming from [spring-test][spring-test] that it used in the tests of the [ksch.patientmanagment.impl][patientmanagment.impl] project. 

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

Those dependencies are visualized in the following [UML Component diagram][cmp]:

![Component diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tv91zc5sd569hsmj0651.png)

## Implementation details

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

```groovy
dependencies {
  testImplementation('com.atlassian.oai:swagger-request-validator-core:2.34.1')
  testImplementation('com.atlassian.oai:swagger-request-validator-mockmvc:2.34.1')
}
```

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](https://bitbucket.org/atlassian/swagger-request-validator/issues/315/validation-failing-for-swagger-with)) and additional properties need to be ignored.

```java
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();
}
```

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

```java
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))
;
```

## References

- [OpenAPI Specification 3.0](https://swagger.io/specification/v3/)
- [Open issues for swagger-request-validator](https://bitbucket.org/atlassian/swagger-request-validator/issues)


[cmp]: https://www.visual-paradigm.com/guide/uml-unified-modeling-language/what-is-component-diagram/
[gradle]: https://www.baeldung.com/gradle
[io.swagger.core]: https://github.com/swagger-api/swagger-core
[io.swagger.parser]: https://github.com/swagger-api/swagger-parser
[jackson]: https://www.baeldung.com/jackson
[java-json-tools]: https://github.com/java-json-tools
[java]: https://en.wikipedia.org/wiki/Java_(programming_language)
[json-schema-validator]: https://github.com/java-json-tools/json-schema-validator
[ksch-workflows-backend]: https://github.com/ksch-workflows/backend
[oas]: https://swagger.io/specification/v3/
[patientmanagment.impl]: https://github.com/ksch-workflows/backend/tree/6a2e2ac86f807690be54e8c402fc9ddc641e29c5/ksch.patientmanagement/ksch.patientmanagement.impl
[spring-test]: https://www.lambdatest.com/blog/spring-testing/
[spring]: https://www.baeldung.com/spring-tutorial
[swagger-core]: https://github.com/swagger-api/swagger-core
[swagger-parser]: https://github.com/swagger-api/swagger-parser
[swagger-request-validator-core]: https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-core/
[swagger-request-validator-mockmvc]: https://bitbucket.org/atlassian/swagger-request-validator/src/master/swagger-request-validator-examples/src/test/java/com/atlassian/oai/validator/examples/mockmvc/?at=master
[swagger-request-validator]: https://bitbucket.org/atlassian/swagger-request-validator