LoginSignup
9
3

More than 3 years have passed since last update.

dreddで認証付きのAPIをテストする

Last updated at Posted at 2020-07-29

しばらく書いてなかったけどメモ程度に

dreddとは

dreddopenapi(swagger)API Blueprintの定義を読み込んでテストを実行してくれる便利なツールです。
例えば localhost:8080 でAPIサーバを動かして

dredd openapi/schema.yaml http://localhost:8080/v1/

のようにすればschema.yamlに定義されたAPIの定義に従ってリクエストを送り、レスポンスが仕様に従っているかテストしてくれます。

が、ログインしてtokenを貰ってそのtokenでアクセスするというようなAPIはそのままではテストできません。
hooksという仕組みを使うと、レスポンスからtokenを取得して以後はそれを使う、といった動作が可能になります。

dredd hooks

ドキュメントにある通り、hooksは様々な言語で書くことができますが、とりあえずdreddと同じnode.jsでやってみます。
(なぜかと言うと、dockerのコンテナ一つで完結させたい場合に処理系を複数入れるのが面倒だから)

schema

例えばこんなschemaがあるとします。(端折っているのでこのままでは動きません)

schema.yaml
openapi: 3.0.2
info:
  title: login api sample
  version: 1.0.0
servers:
  - url: http://localhost:8080/v1
    description: development env
paths:
  /sign_in:
    post:
      description: Sign In
      operationId: signIn
      requestBody:
        required: true
        content:
          application/json; charset=utf-8:
            schema:
              $ref: '#/components/schemas/AuthRequest'
            example:
              email: "foo@bar.jp"
              password: "password"
      responses:
        '200':
          description: successfully authorized
          content:
            application/json; charset=utf-8:
              schema:
                $ref: '#/components/schemas/Auth'
components:
  schemas:
    Auth:
      type: object
      description: authorized response
      properties:
        token:
          type: string
          example: "abcdefgh12345678"
    AuthRequest:
      type: object
      properties:
        email:
          type: string
        password:
          type: string
      required:
        - email
        - password

hooks

hooksは任意のディレクトリに置けますが、 test/hooks/sign_in.js に置くものとします。

sign_in.js
var hooks = require('hooks');
var stash = {};

// hook to retrieve session on a login
hooks.after('/sign_in > POST > 200 > application/json; charset=utf-8', function (transaction) {
  stash['token'] = JSON.parse(transaction.real.body)['token'];
});

// hook to set the session cookie in all following requests
hooks.beforeEach(function (transaction) {
  if(stash['token'] != undefined){
    if (transaction.expected.statusCode != "401"){
      transaction.request.headers['Authorization'] = "Bearer " + stash['token'];
    };
  };
});

実行

dredd openapi/schema.yaml http://localhost:8080/v1/ --hookfiles="test/hooks/*.js"

すると最初に /sign_in にアクセスした時のレスポンスから token を保存し、以降はAuthorizationヘッダに埋め込んでくれます。
ただし 401 のテストの場合は除外するようにしています。

注意点

  • テストはschemaの順番に実行されるので、先頭に /sign_in を書いておかないとそれより前のテストは失敗します。
  • APIの実装によりますが、 ログアウト時にtokenを無効化するようなAPIの場合、ログアウトは最後に書かないと途中でtokenが無効化して以後は失敗します。

その他、hooksを上手く使うと404などの異常系もテストできて便利です。

おわりに

swaggerもdreddも最近使い始めたばかりなので、間違い等ありましたらご指摘ください。
他にもTIPSありましたら教えてくれると嬉しいです。

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3