Swaggerファイルでモックサーバ起動

Swaggerファイルを使用してモックサーバを起動する方法をまとめる。

モックサーバーには prism を使用する。
prism(Github)

仕様書作成準備

作成したAPI仕様書を管理するためのディレクトリを作成し、npm initコマンドを実行する。
以下は作成されたpackage.jsonの例である。

{
  "name": "api",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Swaggerファイルの記述

以下はAPI仕様書のサンプル。

openapi: '3.0.0'
info:
  title: サンプルAPI
  description: API仕様サンプル用
  termsOfService: http://example.com/terms/
  contact:
    name: APIサポートセンター
    url: http://www.example.com/support
    email: support@example.com
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.0
servers:
- url: https://development.example.com
  description: 開発環境
- url: https://staging.example.com
  description: 保守環境
- url: https://{username}.example.com:{port}/v2
  description: 本番環境
  variables:
    username:
      default: taro
      description: ユーザ名
    port:
      enum:
        - '8443'
        - '443'
      default: '8443'
      description: ポート番号
paths:
  /test/customer:
    post:
      summary: お客さま情報登録
      description: お客さま情報を登録する
      tags:
        - customer
      parameters:
        - name: Content-Language
          in: header
          required: true
          schema:
            type: string
            example: ja
      requestBody:
        content:
          text/plain:
            schema:
              type: string
              example: あいうえお
          application/json:
            schema:
              $ref: '#/components/schemas/createCustomerInfo'
      responses:
        '200':
          description: 正常系
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: メッセージ
                    example: "Success"
        '400':
          description: エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    get:
      summary: お客さま情報取得
      description: お客さま情報を取得する
      tags:
        - customer
      parameters:
        - name: id
          in: query
          required: true
          schema:
            type: string
            description: 会員ID
            example: CUS0001
        - name: mail
          in: query
          required: false
          schema:
            type: string
            description: メールアドレス
            example: sample@example.com
      responses:
        '200':
          description: 正常系
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/createCustomerInfo'
  /test/{id}:
    get:
      description: 商品情報を取得する
      tags:
        - item
      security:
        - Bearer: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            description: 商品ID
            example: AA0001
      responses:
        '200':
          description: 正常
components:
  schemas:
    createCustomerInfo:
      description: お客様情報
      type: object
      properties:
        id:
          type: string
          description: 会員ID
          example: AA001
          maxLength: 10
          format: ^[A-Za-z0-9]+$
        name:
          type: string
          description: |
            + 名前
            + aaa
          example: 鈴木太郎
        mail:
          type: string
          description: メールアドレス
          example: taro@co.jp
        age:
          type: number
          description: 年齢
          example: 30
          maximum: 130
          minimum: 20
      required:
        - id
        - name
        - mail
    Error:
      description: エラーオブジェクト
      type: object
      properties:
        code:
          type: string
          description: エラーコード
          example: E00301
        message:
          type: string
          description: エラーメッセージ
          example: IDは必須項目です
  securitySchemes:
    Bearer:
      type: http
      scheme: bearer
      description: アクセストークン
tags: 
- name: customer
  description: お客さま情報操作のAPIグループ
  externalDocs: 
    description: お客さま情報操作のAPIグループに関する追加情報
    url: https://example.com
- name: item
  description: 商品情報操作のAPIグループ
externalDocs:
  description: APIに関する追加情報
  url: https://example.com

モックサーバ起動

◇インストール

npm install @stoplight/prism-cli

インストール後のpackage.jsonは以下の通り。

{
  "name": "api",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "swaggerExport": "redoc-cli build sample.yml --output swagger.html"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@stoplight/prism-cli": "^4.10.0",
    "redoc-cli": "^0.13.16"
  }
}

◇モックサーバーの起動
package.jsonのscriptsに以下の記述を追加する。
ポート番号を指定したい場合はオプションを追加する。
-p : ポート番号(デフォルト:4010)

"swaggerMock": "prism mock sample.yml"

実行コマンド

npm run swaggerMock

停止したい場合は「Ctrl + c」

◇リクエストの送信 モックサーバーに対してAPITesterを使用してリクエストを送信するとレスポンスが正常に返される。

モック実行例

モックサーバー起動からリクエスト送信時の出力

>npx prism mock b.yml
[10:01:35] » [CLI] ...  awaiting  Starting Prism…
[10:01:35] » [CLI] i  info      POST       http://127.0.0.1:4010/test/customer
[10:01:35] » [CLI] i  info      GET        http://127.0.0.1:4010/test/customer?id=sunt
[10:01:35] » [CLI] i  info      GET        http://127.0.0.1:4010/test/ipsa
[10:01:35] » [CLI] ►  start     Prism is listening on http://127.0.0.1:4010
[10:03:01] » [HTTP SERVER] get /test/AA001 i  info      Request received
[10:03:01] »     [NEGOTIATOR] i  info      Request contains an accept header: */*
[10:03:01] »     [VALIDATOR] √  success   The request passed the validation rules. Looking for the best response
[10:03:01] »     [NEGOTIATOR] i  info      Unable to find content for */*. Sending an empty response.
[10:03:01] »     [NEGOTIATOR] √  success   Responding with the requested status code 200

〇レスポンスのHTTPステータスコードを指定する場合
リクエスト送信時のヘッダーに「Prefer: code=401」を追加する

401例

〇同一HTTPステータスコードでレスポンスの例が複数存在する場合に、特定のレスポンスを返却する場合
リクエスト時のヘッダーに「Prefer: example=response2」を追加する
※exampleに指定する値は、返したいレスポンスの名前

特定のレスポンス返却例