やりたいこと
let app = proxyquire('../app.js', stubs);
でスタブにしたいオブジェクトが app.js
に定義されている例はよく見るけど、 「app.js」 -> 「module_a.js」 -> 「module_b.js」 の様に app.js
を require
した先で require
しているオブジェクトを スタブにしたい。
今回は Slackのボットを 「npmモジュールのslack」 を利用して実装している。Slackのチャンネルの一覧を取得するために API slack.channels.list({token})
を使用している。テストコードで本物のAPIを呼び出すわけにはいかないのでスタブに差し替えたい。
tl;dr
- proxyquireのGlobally override requireを使った。
環境
- node.js: v8.10.0
- npmのslack: 11.0.2
- proxyquire: 2.1.0
- mocha: 6.1.4
ソースコード
実装
app.js
var express = require('express');
var commandRouter = require('./routes/slack/command');
var app = express();
./routes/slack/command.js
const Slack = require('slack');
const slack = new Slack();
slack.channels.list({"token":BOT_TOKEN}).then(function(res){
// 受け取ったレスポンスを利用する処理
});
テストコード
/test/command.test.js
const request = require('supertest');
const expect = require('expect');
const proxyquire = require('proxyquire');
// スタブに定義する slack.channels.list の実装
let channelsListSub = function (token) {
return new Promise(function (resolve, reject) {
resolve({
ok: true,
channels: [
{id: "C59K2FFTL", name: "general", members: ["USER1"]}
, {id: "C59MVDJUD", name: "random", members: ["USER2"]}
, {id: "CJCP9UW9H", name: "test1_channel", members: ["USER2"]}
, {id: "CJD0VJUE6", name: "test2_channel", members: ["USER2"]}
]
})
})
}
// require('slack') で読み込まれるスタブを定義
let stubs = {
'slack': function () {
this.channels = {
list: channelsListSub
}
}
};
stubs.slack['@global'] = true;
let app = proxyquire('../app.js', stubs);
it('スラッシュコマンド mycommand', (done) => {
const qs = {
command: '/mycommand',
text: '',
// スラッシュコマンで渡られる他のパラメータが続く
};
request(app)
.post('/command')
.type('form')
.send(qs)
.expect(200, {
text: "期待するメッセージ"
})
//非同期処理のテストの際にdoneでキチンと終了を知らせる
.end(done);
})
説明
テストコード test/command.test.js
の let app = proxyquire('../app.js', stubs);
で読み込みを行うと、連鎖的に app.js
-> routes/slack/command.js
-> node_moduels の slack
が読み込まれる。
先に
let stubs = {
'slack': function () {
this.channels = {
list: channelsListSub
}
}
};
でスタブを定義して
stubs.slack['@global'] = true;
で Globally override require の指定を行う