APIサーバのレスポンスがスキーマ上のレスポンス定義と一致するかのテスト


committeecommittee-railsが(わからなかった|動かなかった)ので、WEB+DB PRESS Vol.108に記載されている方法でやってみた。

ざっくり言うと

oas_parserでswagger.jsonをパースして、json_schemaでバリデーションを行う

gem


gem 'oas_parser'
gem 'json_schema'

swagger.json

{
  "swagger": "2.0",
  "info": {
    "title": "API V1",
    "version": "v1"
  },
  "servers": [
    {
      "url": "http://localhost:3000/api-docs",
      "description": "development server"
    }
  ],
  "basePath": "/api/v1",
  "paths": {
    "/areas/{id}": {
      "get": {
        "summary": "Retrieves a area",
        "tags": [
          "Areas"
        ],
        "description": "Retrieves a specific area by id",
        "operationId": "getArea",
        "security": [
          {
            "apiKey": [

            ]
          }
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name":        "id",
            "in":          "path",
            "type":        "integer",
            "description": "エリアID",
            "required":    true
          }
        ],
        "responses": {
          "200": {
            "description": "success",
            "schema": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "name": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "name"
              ]
            }
          }
        }
      }
    },
    "securityDefinitions": {
    "apiKey": {
      "type": "apiKey",
      "name": "Authorization",
      "in": "header"
    }
  }
}

SchemaオブジェクトとJSON Schemaライブラリを用いてJSONのバリデーションを行う

  • spec/rails_helper.rb
RSpec.configure do |config|
  config.include ControllerSpecsHelper

  config.before :example, type: :controller do
    spec        = OasParser::Definition.resolve(Rails.root.join('swagger', 'v1', 'swagger.json'))
    schema_data = spec.path_by_path(schema_path).endpoint_by_method(schema_method).response_by_code(code.to_s).raw["schema"]
    @schema     = JsonSchema.parse!(schema_data) if schema_data
  end
  • spec/support/controller_specs_helper.rb
module ControllerSpecsHelper
  def expect_to_conform_schema(response)
    expect {
      @schema.validate!(JSON.parse(response.body))
    }.not_to raise_error
  end
end

テスト

require 'rails_helper'

RSpec.describe Api::V1::AreasController, type: :controller do
  render_views

  describe 'GET #show' do
    let(:schema_path)   { '/areas/{id}' }
    let(:schema_method) { 'get' }
    let(:code)          { 200 }

    it 'conform json schema' do
      expect_to_conform_schema response
    end

  end
end