我们有一些我们想要测试的node.js代码.这些是返回函数的模块(module.exports = function(){…}).在函数内部,需要一些其他模块.现在我们要模拟这些模块.见下面的例子:
// userRepo.js
module.exports = function(connection) {
// init the repo
var repo = DB.connect(connection);
// add validation function
repo.validate = function(data, cb) {
// do validation stuff
cb(error, result);
};
return repo;
};
// userController.js
module.exports = function(config) {
var repo = require('userRepo.js')(config.connectionStringToUserDB)
var pub = {};
pub.create = function(data, cb) {
repo.validate(data, function(err, res) {
// do some stuff
};
};
return pub;
}
// the test
var sut = require('userController.js')(anyConfig);
sut.create({}, function(err, res) {
// do some assertions here
};
所以在测试中我们想要模拟/存储函数repo.validate().但直到现在我们才发现这样做.我们测试的所有node.js模拟框架/库都可以模拟一个模块然后你可以覆盖导出.但在我们的例子中,模块返回一个函数,并且在控制器中,repo已经被实例化.
我希望我的解释是可以理解的:-)
谢谢你的帮助.
最佳答案 我认为如果不改变代码中的内容,就不能解决问题.这是因为repo变量是userRepo.js的私有变量.但是我真的很喜欢这种情况,因为现在你发现模块设计不正确并且无法完全测试.我会这样写的.
// userRepo.js
module.exports = function(connection) {
var api = {}, repo;
api.setRepo = function(r) {
repo = r;
}
api.getRepo = function() {
return repo;
}
api.init = function() {
// init the repo
repo = repo || DB.connect(connection);
// add validation function
repo.validate = function(data, cb) {
// do validation stuff
cb(error, result);
};
}
return api;
};
所以,做这样的事情你将能够模拟repo varialbe并使用自定义验证方法传递你自己的变体.当然问题是你应该改变你使用userRepo.js的地方
var userRepo = require("./userRepo.js")(connection)
至
var userRepo = require("./userRepo.js")(connection).init();
但它值得.因为在你的测试中你可以写:
var userRepo = require("./userRepo.js")(connection).setRepo(customRepo).init();
甚至
var userRepo = require("./userRepo.js")(connection);
var repo = userRepo.getRepo();
repo.validate = function() {
// custom stuff here
}
userRepo.init();
所以我的建议是:在开始写作之前先问问自己“我将如何测试它?”.