在async.each中生成错误

时间:2015-02-19 12:21:35

标签: javascript node.js unit-testing node-async

我有以下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); ...

的路径

为此,我看到依赖注入重新连接(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)'。并且没有错误。

我做错了什么?我已经在类似的用例中使用了重新连接,它运行得很好。还是有另一种方法吗?

2 个答案:

答案 0 :(得分:0)

这是rewire所做的事情:

  1. 对于每个重新路由的路径,它实际上会读取路径指向的文件的内容,我们称之为body
  2. 它还会生成两个字符串,第一个字符串称为prelude,它有一些有用的变量,以避免使用__set__覆盖全局字符串,例如如果我们想要覆盖全局console,好像它是我们模块上的本地prelude var的内容将是:var console = global.console,这个可以在本地覆盖的全局变量的真棒检测是完成here
  3. 第二个称为appendix,此字符串实际上包含__set____get__的定义,还有__with__ {{3} },每个都是module.exports定义的函数,但请记住我们仍在处理字符串
  4. 想象一下,有一种方法可以用字符串创建假/测试模块!这是wired的作用,它将preludebodyappendix连接在一个大字符串中,然后创建一个{{1}的模块}
  5. e.g。 (记住这是一个很大的字符串)

    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做了什么,source归结为以下操作:

    __set__

    现在我们知道执行function (key, value) { eval(key + ' = ' + value); } 只会将您想要的任何密钥(对我们来说都是本地__set__)进行评估,将其设置为{{1}但在此test / fake模块中

    现在回到你的问题,我发现这可能是它的来源:

    var

    我假设value可能被定义为new CdObjectOutputModel(...); 的子类,但请记住,在您的测试中CdObjectOutputModel实际上是一个测试/假冒模块,因此您可以并没有真正重写MyOutputModel的原始代码,而是覆盖了仅存在于本地的副本,我想你必须重新连接var MyOutputModel = rewire('...');或者本地制作{ {1}}继承自MyOutputModel

    的重新连接版本

答案 1 :(得分:0)

只需用errorCallback替换回调,它应该可以正常工作。