LoginSignup
4
0

More than 3 years have passed since last update.

proxyquire で 間接的に require するオブジェクトは @global で差し替える

Posted at

やりたいこと

let app = proxyquire('../app.js', stubs); でスタブにしたいオブジェクトが app.js に定義されている例はよく見るけど、 「app.js」 -> 「module_a.js」 -> 「module_b.js」 の様に app.jsrequire した先で require しているオブジェクトを スタブにしたい。

今回は Slackのボットを 「npmモジュールのslack」 を利用して実装している。Slackのチャンネルの一覧を取得するために API slack.channels.list({token}) を使用している。テストコードで本物のAPIを呼び出すわけにはいかないのでスタブに差し替えたい。

tl;dr

環境

  • 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.jslet 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 の指定を行う

4
0
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
4
0