loopback-testingを利用してloopbackで作成したAPIのテストを書く

loopbackでAPIのテストを書く際にloopback-testingを利用してAPIのテストを書いてみたのでその際のメモ。

まずは必要なnpmパッケージをloopbackアプリケーションに導入します。loopbackアプリのルートで以下のnpmコマンドを実行。

www.npmjs.com

$ npm install loopback-testing --save-dev
$ npm install chai --save-dev

これで準備完了。加えて npm test でテストを実行できる様に package.json 内のscriptsの定義を以下の様に書き換えます。*1

"scripts": {
"test": "NODE_ENV=\"testing\" ./node_modules/loopback-testing/node_modules/.bin/mocha -R spec --recursive"
}

上記の意図は npm test が実行された際に testing 環境としてnode_modules配下のmochaを利用してテストを実行します。

それにともなってtesting環境でloopbackアプリが実行された際のデータソース(DB接続先)を定義しておきます。Circle CI等のCI環境でもすぐに実行できる様に、memoryを指定します。

~/server/datasources.testing.js というファイルを用意して以下の様にデータの保存先をmemoryに指定します。

module.exports = {
  db: {
    connector: "memory",
    defaultForType: "db"
  }
};

これでテストが実行できる様になりました。expressの流儀と同様にプロジェクト直下の test ディレクトリに現在開発しているloopbackアプリケーション(API)のテストを書いてみます。

例えばユーザ登録(メールアドレスとPWをPOSTするとユーザ登録できる)のAPIのテストであれば、

var lt = require('loopback-testing');
var chai = require('chai');
var assert = chai.assert;
var app = require('../../server/server.js');

describe('/api/users', function() {
  var newUser = {email: "tester1@remp.jp", password:"tester1remp"};

  describe('ユーザ登録', function() {
    lt.describe.whenCalledRemotely('POST', '/api/users', {}, function() {
      it('ユーザ登録の際にメールアドレス、パスワードのパラメータは必須', function() {
        var codes = this.res.body.error.details.codes;
        assert.include(codes.password, 'presence');
        assert.include(codes.email, 'presence');
        assert.include(codes.email, 'format.null');
      });
    });

    lt.describe.whenCalledRemotely('POST', '/api/users', newUser, function() {
      it('メールアドレス, パスワードを与えるとユーザ作成できる', function() {
        assert.equal(this.res.statusCode, 200);
      });
    });
  });
});

といった具合に記述することができます。

ほぼコードを読んだままなのですが、 lt.describe.whenCalledRemotely の記述で指定のエントリポイント下へ指定のメソッド及びパラメータでアクセスがあった場合のテストを書くことができます。

また、アクセスするユーザにロールや状態をもたせた状態のテストも同様に記述ができ、例えばログインを行ったユーザによるAPIへのアクセスを想定したテストは

  var user = {
    id: 2,
    email: "tester2@remp.jp",
    username: "tester2",
    password: "tester2remp"
  };

  // (snip)

  describe('ユーザによるプレイリスト操作', function() {
    lt.describe.whenCalledRemotely('GET', '/api/users/2/playlists', function() {
      it('未ログインユーザはユーザのプレイリストは取得できない', function() {
        assert.equal(this.res.statusCode, 401);
      });
    });

    lt.describe.whenCalledByUser(user, 'GET', '/api/users/2/playlists', function() {
      it('ログインしたユーザ自身のプレイリストは取得できる', function() {
        assert.equal(this.res.statusCode, 200);
      });
    });
  });

の様に lt.describe.whenCalledByUser という記述で実現することができます。他にも各種ロールを割り当てた上での記述が行える様になっています。

こういった形でテストを用意した上で npm test で実行してみると...

といった具合にmochaによるテストが実行できています。

loopbackで作成したAPIであれば、loopback-testingを用いることでアクセスするユーザの各種ロールを想定したテストが記述できて便利ですというお話でした。

まとめ

  • loopbackアプリケーションでのテストを行うために loopback-testing を導入しました
  • npm test でテストを実行できる様にpackage.jsonの一部を修正しました
  • whenCalledRemotely, whenCalledByUser 等 loopback-testingを利用することで用意に各種ロールを想定したテストが書けました

あわせて読みたい

*1:loopbackのscafold(slcコマンド)で作成された場合は仮のpretestの定義が書いてあります