1

次の JavaScript があります。

var async = require('async');

var MyOutputModel = function(persistenceModel, callback) {
    async.each(persistenceModel.helpOffers, function(helpOffer, asyncCallback) {
        console.log('Original source (loop)');
        //Do something ...
        asyncCallback();
    }, function(err) {
        console.log('Original source (done)');
        console.log(err);
        if(err) return callback(err);
        return callback(null, _this);
    });
};
module.exports = MyOutputModel;

if(err) return callback(err);...を含むパスをテストしたい

そうするために、rewire ( https://www.npmjs.com/package/rewire ) による依存性注入の唯一の可能性を見ています。

私の単体テストでは:

var rewire = require('rewire');    
var MyOutputModel = rewire('...');

var AsyncMock = function() {};
AsyncMock.prototype.each = function(array, successCallback, errorCallback) {
    console.log('Inside mock!');
    callback(new Error());
};
var asyncMock = new AsyncMock();

MyOutputModel.__set__('async', asyncMock); //Rewire for require-dependency-injection

//Act
new CdObjectOutputModel(cdObjectPersistenceModel, function(err, cdObjectOutputModel) {

    //Assert
    assert(err);
});

ただし、「モック」は使用されていないようです。私のユニットテストでは、私はコンソールにしか表示され'Inside mock!'ませ'Original source (loop)'ん。'Original source (done)'そして、エラーはありません。

私が間違っていることはありますか?私はすでに同様のユースケースで rewire を使用しており、完全に機能しました。それとも別のアプローチがありますか?

4

2 に答える 2

0

これはrewireボンネットの下で行うことです:

  1. 再配線されたパスごとに、パスが指すファイルの内容を実際に読み取ります。body
  2. また、2 つの文字列を生成します。最初の文字列は the と呼ばれ、グローバルなものをでprelude上書きしないようにするための便利な変数がいくつかあります。be: 、ローカルでオーバーライドできるグローバルのこのすばらしい検出は、ここで行われます__set__consolepreludevar console = global.console
  3. 2 つ目は the と呼ばれ、appendixこの文字列には実際に の定義が含まれています__set__。さらにsource__get__もあります。それぞれが上で定義された関数ですが、まだ文字列を扱っていることを思い出してください。__with__ module.exports
  4. 文字列から偽の/テストモジュールを作成する方法があると想像してみてください! 、 、を 1 つの大きな文字列wiredに連結し、prelude次のモジュールを作成します。bodyappendixrequire('module')

例 (これは大きな文字列であることを思い出してください)

// prelude start
var console = global.console
// a lot of globals that can be overriden are defined here :)
// prelude end

// body start
// I'll paste the contents of the rewire's README
var fs = require("fs");
var path = "/somewhere/on/the/disk";
function readSomethingFromFileSystem(cb) {
    console.log("Reading from file system ...");
    fs.readFile(path, "utf8", cb);
}
exports.readSomethingFromFileSystem = readSomethingFromFileSystem;
// body end

// appendix start
// generation of three functions to set the variables defined above
Object.defineProperty(module.exports, '__set__', {
  enumerable: false,
  value: function () {
    // set contents, we will see this later
  }
});
Object.defineProperty(module.exports, '__get__', { ... });
Object.defineProperty(module.exports, '__with__', { ... });
// appendix end

つまりrewire、この文字列を使用してモジュールを作成し、それを返すと、3 つの追加プロパティを持つ魔法のモジュールができあがります。次のステップは実際に何__set__が機能するかを調べることです__set__ソースは次の操作に要約されます。

function (key, value) {
  eval(key + ' = ' + value);
}

これで、実行する__set__と、必要なキー (私たちにとっては任意の local ) が評価され、このテスト/偽のモジュールでのみvar設定されることがvalueわかりました。

問題に戻ると、これが原因である可能性があります。

new CdObjectOutputModel(...);

CdObjectOutputModelおそらくのサブクラスとして定義されているMyOutputModelと思いますが、テストvar MyOutputModel = rewire('...');では実際にはテスト/偽のモジュールであるため、元のコードを実際にオーバーライドするのではなく、ローカルにのみ存在するそのコピーMyOutputModelの種類をオーバーライドしていることを覚えておいてください。再配線するか、おそらくローカルで再配線バージョンから継承する必要があると思いますCdObjectOutputModelCdObjectOutputModelMyOutputModel

于 2015-03-05T05:51:06.600 に答える