我有以下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)'
。并且没有错误。
我做错了什么?我已经在类似的用例中使用了重新连接,它运行得很好。还是有另一种方法吗?
答案 0 :(得分:0)
这是rewire
所做的事情:
body
prelude
,它有一些有用的变量,以避免使用__set__
覆盖全局字符串,例如如果我们想要覆盖全局console
,好像它是我们模块上的本地prelude
var的内容将是:var console = global.console
,这个可以在本地覆盖的全局变量的真棒检测是完成here appendix
,此字符串实际上包含__set__
,__get__
的定义,还有__with__
{{3} },每个都是module.exports
定义的函数,但请记住我们仍在处理字符串wired
的作用,它将prelude
,body
和appendix
连接在一个大字符串中,然后创建一个{{1}的模块} 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替换回调,它应该可以正常工作。