簡體   English   中英

在async.each中產生一個錯誤

[英]Producing an error in async.each

我有以下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);的路徑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用於類似的用例,並且效果很好。 還是有另一種方法?

這是rewirerewire執行的操作:

  1. 對於每個重新連接的路徑,它實際上將讀取路徑所指向的文件的內容,我們將其稱為body
  2. 它還會生成兩個字符串,第一個稱為prelude ,它具有一些有用的var,可以避免使用__set__覆蓋全局__set__ ,例如,如果我們想覆蓋全局console ,就好像它在模塊中位於本地一樣,的prelude VAR將是: var console = global.console ,全局的這真棒檢測它可以在本地覆蓋完成后這里
  3. 第二個稱為appendix ,此字符串實際上包含__set____get__的定義,還有__with__ ,每個都是在module.exports定義的函數,但請記住,我們仍在處理字符串
  4. 想象一下,有一種方法可以用字符串創建一個假/測試模塊! 這就是wired工作,將preludebodyappendix成一個大字符串,然后創建一個帶有require('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要做的就是用這個字符串創建一個模塊並返回它,瞧,您有一個具有三個附加屬性的魔術模塊,下一步實際上是找出__set__作用, __set__源可以歸結為以下操作:

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

就是這樣,現在我們知道執行__set__只會評估要設置為value任何鍵(對我們來說是任何本地var ),但只能在此test / fake模塊中設置。

現在回到您的問題,我看到這可能是它的根源:

new CdObjectOutputModel(...);

我假設CdObjectOutputModel可能定義為MyOutputModel的子類,但請記住,在您的測試中var MyOutputModel = rewire('...'); 實際上是一個測試/偽造模塊,因此您並沒有真正覆蓋MyOutputModel的原始代碼,而是覆蓋了僅存在於本地的MyOutputModel副本 ,我想您必須重新連接CdObjectOutputModel或在本地使CdObjectOutputModel從重新連接的版本繼承MyOutputModel

只需將回調替換為errorCallback,它就可以正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM