web-dev-qa-db-ja.com

モジュール機能のスタブアウト

編集:もう少し正確であること。

私たちのチームが作成したGithubAPIラッパー拡張機能のユースケースをテストしたいと思います。テストでは、APIラッパー拡張機能を直接使用したくないので、その関数をスタブ化します。クローンスタブを作成するだけでなく、APIラッパーへのすべての呼び出しをテスト用にスタブアウトする必要があります。

Node.jsにモジュール「github」があります。

_module.exports = function(args, done) {
    ...
}
_

そして私はそれをこのように要求しています:

_var github = require('../services/github');
_

ここで、Sinon.jsを使用してgithub(...)をスタブアウトしたいと思います。

_var stub_github = sinon.stub(???, "github", function (args, callback) { 
    console.log("the github(...) call was stubbed out!!");
});
_

しかし、sinon.stub(...)は、オブジェクトとメソッドを渡すことを期待しており、関数であるモジュールをスタブアウトすることを許可していません。

何か案は?

11
mitchkman

純粋なシノンでこれを達成する方法があるかもしれませんが、それはかなりハッキーだと思います。ただし、 proxyquire は、この種の問題を解決するために設計されたノードライブラリです。

Githubモジュールを利用するモジュールfooをテストしたいとします。あなたは次のようなものを書くでしょう:

var proxyquire = require("proxyquire");
var foo = proxyquire(".foo", {"./github", myFakeGithubStub});

ここで、myFakeGithubStubは何でもかまいません。完全なスタブ、またはいくつかの調整を加えた実際の実装など。

上記の例で、myFakeGithubStubのプロパティ "@global"がtrueに設定されている場合(つまり、myFakeGithubStub["@global"] = true)次に、githubモジュールは、fooモジュール自体だけでなく、fooモジュールが必要とするすべてのモジュールでスタブに置き換えられます。ただし、 グローバルオプションに関するproxyquireドキュメント で述べられているように、一般的に言えば、この機能は不十分に設計された単体テストの兆候であり、避ける必要があります。

9
Retsam

私はこれが私のために働いたことがわかりました...

const sinon          = require( 'sinon' );
const moduleFunction = require( 'moduleFunction' );

//    Required modules get added require.cache. 
//    The property name of the object containing the module in require.cache is 
//    the fully qualified path of the module e.g. '/Users/Bill/project/node_modules/moduleFunction/index.js'
//    You can get the fully qualified path of a module from require.resolve
//    The reference to the module itself is the exports property

const stubbedModule = sinon.stub( require.cache[ require.resolve( 'moduleFunction' ) ], 'exports', () => {

    //    this function will replace the module

    return 'I\'m stubbed!';
});

// sidenote - stubbedModule.default references the original module...

他の場所で必要になる前に、(上記のように)モジュールをスタブ化することを確認する必要があります...

// elsewhere...

const moduleFunction = require( 'moduleFunction' ); 

moduleFunction();    // returns 'I'm stubbed!'
6
Ben Davies

最も簡単な解決策は、モジュールをリファクタリングすることです。

これの代わりに:

module.exports = function(args, done) {
    ...
}

これを行う:

module.exports = function(){
    return module.exports.github.apply(this, arguments);
};
module.exports.github = github;

function github(args, done) {
    ...
}

今、あなたはそれを要求することができます:

const github = require('../services/github.js');
//or
const github = require('../services/github.js').github;

スタブへ:

const github = require('../services/github.js');
let githubStub = sinon.stub(github, 'github', function () {
    ... 
});
3
Demeter