Node.js (Mocha + Chai) でWeb APIのレスポンスをテストするサンプル
作ったWeb APIを外から叩いてテストしたので、基本的なところのメモです。
[2019-07-09追記] 当ブログの下記記事の方が、新しくて簡潔かもしれません。
MochaとChaiでなんでもテスト ~WebAPI編~ - キリウ君が読まないノート
準備
根本的なところから書いときます。
まずNode.jsをインストールしてパスを通し、node
および npm
コマンドを使えるようにしておきます。Windowsの場合、Node.jsをインストールしたフォルダの直下に通せばOKです。
任意のカラのフォルダを作成し、コマンドプロンプトで cd
で当該フォルダに移動して以下コマンドを実行します。いろいろ聞かれますが、全部何も入力せずにエンターキーでOKです。
npm init
その後、以下コマンドを実行して、必要なものをインストールします。これらは自動的に作成された node_modules
フォルダにダウンロードされます。
npm install mocha --save-dev
npm install chai --save-dev
npm install request --save-dev
Web APIの仕様
この記事のプログラムで叩く、架空のWeb APIの仕様です。一応RESTfulですが、架空なのでガバガバです。
URL https://api.example.com/user/update
で、次のように呼び出すWeb APIが存在するとします。
- リクエストメソッドはPOST。
- リクエストヘッダは
Content-Type: application/json
が必須。 - リクエストボディはJSON形式で、キー
user_id
およびname
を設定する。
想定されるレスポンスは、とりあえずここでは以下のものだけとします。
問題なし (正常系)
ステータスコードは200、レスポンスボディは以下のJSONです。
{
"message":"更新完了"
}
リクエストボディがJSON形式ではない場合
ステータスコードは400、レスポンスボディは以下のJSONです。
{
"error":"パラメータをパースできませんでした"
}
リクエストボディに user_id
が含まれてない場合
ステータスコードは422、レスポンスボディは以下のJSONです。
{
"error":{
"user_id":"ユーザーIDを指定してください。"
}
}
テストプログラムを書く
この架空のWeb APIについて、想定されるレスポンスをテストするプログラムを書きます。
基本的なところは以下の記事を参考にさせていただきました。
ユニットテストって何?って人向けのmochaとchaiの使い方 - Qiita
mocha
と chai.assert
の詳細は、公式サイトを参照してください。
Mocha - the fun, simple, flexible JavaScript test framework
準備したフォルダに test.js
ファイルを作成し、内容を以下のサンプルコードの通りにします。
'use strict';
const chai = require('chai');
const assert = chai.assert;
const request = require('request');
const URL = 'https://api.example.com/user/update';
/**
* テスト用にPromise化したrequest
* リクエスト成功さえすれば、ステータスコードに関わらずresolveにレスポンスを返す
* @param {Object} options - requestに渡すオプション
* @return {Promise}
*/
const pRequest = (options) => {
return new Promise(function(resolve, reject) {
request(options, function(error, res, body) {
if (error) {
reject(error);
} else {
resolve(res);
}
});
});
};
// テスト本体
describe('Web APIのレスポンス', async function() {
this.timeout(10000); // デフォルトのタイムアウトが 2000ms なので 10000ms に延ばしておく
// 問題なし (正常系)
it('ステータスコード200, メッセージ=更新完了', async function() {
const res = await pRequest({
url: URL,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
user_id: 99,
name: 'キリウ君'
})
});
assert.strictEqual(res.statusCode, 200, 'ステータスコード');
try {
const body = JSON.parse(res.body);
assert.strictEqual(body.message, '更新完了', 'レスポンスボディ');
} catch (e) {
assert.fail('レスポンスがJSON形式じゃない!');
}
});
// リクエストボディがJSON形式ではない場合
it('ステータスコード400, エラー=パラメータをパースできませんでした', async function() {
const res = await pRequest({
url: URL,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: 'あああああ'
});
assert.strictEqual(res.statusCode, 400, 'ステータスコード');
try {
const body = JSON.parse(res.body);
assert.strictEqual(body.message, 'パラメータをパースできませんでした', 'レスポンスボディ');
} catch (e) {
assert.fail('レスポンスがJSON形式じゃない!');
}
});
// リクエストボディに user_id が含まれてない場合
it('ステータスコード422, エラー=user_id: ユーザーIDを指定してください。', async function() {
const res = await pRequest({
url: URL,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'キリウ君'
})
});
assert.strictEqual(res.statusCode, 422, 'ステータスコード');
try {
const body = JSON.parse(res.body);
assert.hasAllDeepKeys(body, ['error'], 'レスポンスボディ');
assert.hasAllDeepKeys(body.error, ['user_id'], 'error の内容');
assert.strictEqual(body.error.user_id, 'ユーザーIDを指定してください。', 'error.user_id の内容');
} catch (e) {
assert.fail('レスポンスがJSON形式じゃない!');
}
});
});
一番上にPromise化した request
なるものがありますが、これは request
を使ったテストを async
/await
ですっきり書くためのものです。リクエスト自体に成功さえすれば、常に生のレスポンスオブジェクトを resolve
に渡すようになってます。
起動方法
この時点で、用意したフォルダの中身はこうなってます。
当該フォルダ
├ node_modules
│ ├ .bin
│ └ (mocha, chai, request とそれらが依存するライブラリたち)
├ package.json
├ package-lock.json
└ test.js
コマンドプロンプトでカレントディレクトリが当該フォルダになっていることを確認し、以下コマンドを実行します。
.\node_modules\.bin\mocha test.js
すると先程のテストプログラムが実行されます。
今回のWeb APIがもし実在するなら、以下のような感じで結果が表示されるはずです。
Web APIのレスポンス
√ ステータスコード200, メッセージ=更新完了 (750ms)
√ ステータスコード400, エラー=パラメータをパースできませんでした (751ms)
√ ステータスコード422, エラー=user_id: ユーザーIDを指定してください。 (701ms)
3 passing (5s)
以上です。