Validate APIs using OpenAPI and IntelliJ HTTP Client
Tags: intellij, testing, json, api
Published: 2024-04-09 02:50:09

---
title: Validate APIs using OpenAPI and IntelliJ HTTP Client
published: true
description: How to validate responses of JSON-APIs using IntelliJs HTTP Client against JSON schemas defined in OpenAPI schema files
tags: [IntelliJ, Testing, JSON, API]
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m109gbtz1m2qyrt8m5qe.png
---

## Introduction
When it comes to the development of a new API, a good approach is always to define the API contract first. This can be done using [OpenAPI](https://www.openapis.org/) (formerly known as Swagger). It defines the structure of the API and how to interact with it. OpenAPI uses [JSON Schema](https://json-schema.org/) to define the structure of the request and response bodies.

## What's already out there?
When developing an API, it is important to validate the responses of the API. Now that we have the contract defined in an OpenAPI schema file, we can use this schema to validate the responses of the API – but how?

There are some tools out there which can validate a JSON response against a JSON schema defined in an OpenAPI schema file. One of the most popular tools for testing APIs in my social bubble is [Postman](https://www.postman.com/). Postman is a great tool for testing APIs, but it is not OSS, it is not integrated into the IDE and some of the features I really like are behind a paywall.

So, why not use the tools we already have? I like the [HTTP Client](https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html) in IntelliJ IDEA a lot, because it integrates well in my favorite IDE, it uses simple text files for the definition which allows a good integration into version control systems, and compared to other tools, you can see the whole configuration and scripts in a single file.

IntelliJ HTTP Client still misses a lot of features to be a full replacement for postman, but the most important feature I was missing was the ability to validate the response against a JSON schema – until now 🥳!

## HTTP Client schema check
[HTTP Client schema check](https://gitlab.com/http-client-schema-check/http-client-schema-check) is a code generator to generate code for IntelliJ HTTP Client to validate responses against JSON schemas defined in OpenAPI schema files.

Its usage is simple:
1. Define your API contract in an OpenAPI schema file.
2. Run the code generator to generate the necessary code for IntelliJ HTTP Client.
3. Use the generated code in your HTTP Client response handler script to validate the responses against the defined JSON schema.
4. Profit 🎉!

## Example
Let's say you have an API like the [Swagger Petstore](https://petstore3.swagger.io/) and you want to write some test for its API-Implementation.

The OpenAPI schema file `petstore.yaml` is your local workspace in the directory `./schema` and you have [podman](https://podman.io/) or [docker](https://www.docker.com/) installed.

To have a consistent naming of the generated functions, the operationId and the response code are used to generate the function name. This implies, that the [operationId](https://swagger.io/specification/#operation-object) is properly set in the OpenAPI schema file.

```yaml
openapi: 3.0.2
info:
  title: Swagger Petstore - OpenAPI 3.0
  version: 1.0.19
paths:
  /pet/{petId}:
    get:
      operationId: getPetById
      parameters:
        - name: petId
          in: path
          required: true
      responses:
        "200":
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Pet'
components:
  schemas:
    Category:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
    Tag:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
    Pet:
      required:
        - name
        - photoUrls
      type: object
      properties:
        id:
          type: integer
          format: int64
          example: 10
        name:
          type: string
          example: doggie
        category:
          $ref: '#/components/schemas/Category'
        photoUrls:
          type: array
          xml:
            wrapped: true
          items:
            type: string
            xml:
              name: photoUrl
        tags:
          type: array
          xml:
            wrapped: true
          items:
            $ref: '#/components/schemas/Tag'
        status:
          type: string
          description: pet status in the store
          enum:
            - available
            - pending
            - sold
```


To generate the validation code, you only need to run the generator with the path to the directory containing your OpenAPI schema file:
```shell
podman run --rm -it --security-opt="label=disable" -v $(pwd)/schema:/app/openapi registry.gitlab.com/http-client-schema-check/http-client-schema-check:latest
```

This will end up with a file named `validate-petstore.js` in the directory `./schema` which contains the generated code to validate the response of the API. All you need to do now is to import the correct function in your IntellJ HTTP Client response handler script and use it to validate the response.

```javascript
GET https://petstore3.swagger.io/api/v3/pet/10
accept: application/json

> {%
    import { getPetById_200 as validate } from '../schema/validate-petstore.js'

    client.test("Request status is 200", function() {
        client.assert(response.status === 200, "Response status is not 200 but " + response.status);
    })

    client.test("Response body is valid", function() {
        client.assert(validate(response.body), "Response body is invalid: " + JSON.stringify(validate.errors))
    })
%}
```

## CI/CD or IntelliJ community
Thanks to the [HTTP Client cli tool](https://www.jetbrains.com/help/idea/http-client-cli.html), you can run the HTTP Client scripts in your CI/CD pipeline or on a local container engine without purchasing a license for IntelliJ IDEA Ultimate.

If you want to run the tests on a machine which is not a workstation like in a CI/CD pipeline, you might consider building a dedicated container image for the test runs:

```dockerfile
# tests.Containerfile
FROM registry.gitlab.com/http-client-schema-check/http-client-schema-check:latest AS generator
COPY schema/petstore.yaml /app/openapi/petstore.yaml
RUN node create-validators.js

FROM docker.io/jetbrains/intellij-http-client AS runner
COPY --from=generator /app/openapi/validate-petstore.js /workdir/schema/validate-petstore.js
COPY tests/petstore.http /workdir/tests/petstore.http
CMD ["tests/petstore.http"]
```

### GitLab CI

Running these images in GitLab CI require some adjustments. e.g. if you want to run them scheduled:

```yaml
testimage-build:
  image:
    name: quay.io/buildah/stable:latest
  stage: test
  before_script:
    - 'echo "$CI_REGISTRY_PASSWORD" | buildah login --username "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY'
  script:
    # no expensive builds are done, skipping layer-cache
    - buildah bud
      -f "tests.Containerfile"
      -t "$CI_REGISTRY_IMAGE/tests:$CI_COMMIT_SHORT_SHA"
      .
    - buildah push "$CI_REGISTRY_IMAGE/tests:$CI_COMMIT_SHORT_SHA"

testimage-run:
  image:
    name: "$CI_REGISTRY_IMAGE/tests:$CI_COMMIT_SHORT_SHA"
    entrypoint: [""]
  script:
    - java $IJHTTP_JAVA_OPTS -cp "/intellij-http-client/*" "com.intellij.httpClient.cli.HttpClientMain" /workdir/tests/petstore.http --report
  artifacts:
    reports:
      junit: reports/report.xml
  needs:
    - job: testimage-build

```

## So long, and thanks for all the fish

I hope you enjoyed this post and that you will sleep even better in the future because you know, that your APIs are not only correctly implemented, but you also know that they are still up and running.

If you liked this post so much that you want to buy me a coffee, you can do so via [buymeacoffee.com/blaimi](https://www.buymeacoffee.com/blaimi)