测试Node.js,模拟并测试一个需要的模块?
我正在努力围绕我的节点模块编写高质量的测试。问题是需求模块系统。我希望能够检查某个需要的模块是否有方法或其状态已更改。似乎有两个相对较小的库可用于此处:node-gently和mockery。然而,由于他们的'个人资料'较低,这让我认为任何人都不会对此进行测试,或者有另一种做法,我不知道。测试Node.js,模拟并测试一个需要的模块?
什么是模拟和测试需要的模块的最佳方法?
----------- UPDATE在同校长---------------
node-sandbox作品说明以下,但被包裹在一个很好的模块中。我发现与它合作非常愉快。
--------------- 详细awnser ---------------
经过多次试验我找到最好的方法来孤立地测试节点模块,同时嘲笑事情的方法是使用Vojta Jina的方法在新的上下文中运行每个模块,如here所述。
这个测试虚拟测量模块:
var vm = require('vm');
var fs = require('fs');
var path = require('path');
/**
* Helper for unit testing:
* - load module with mocked dependencies
* - allow accessing private state of the module
*
* @param {string} filePath Absolute path to module (file to load)
* @param {Object=} mocks Hash of mocked dependencies
*/
exports.loadModule = function(filePath, mocks) {
mocks = mocks || {};
// this is necessary to allow relative path modules within loaded file
// i.e. requiring ./some inside file /a/b.js needs to be resolved to /a/some
var resolveModule = function(module) {
if (module.charAt(0) !== '.') return module;
return path.resolve(path.dirname(filePath), module);
};
var exports = {};
var context = {
require: function(name) {
return mocks[name] || require(resolveModule(name));
},
console: console,
exports: exports,
module: {
exports: exports
}
};
vm.runInNewContext(fs.readFileSync(filePath), context);
return context;
};
有可能测试每个模块都有自己的背景,轻松地踩灭了所有外部dependencys。
fsMock = mocks.createFs();
mockRequest = mocks.createRequest();
mockResponse = mocks.createResponse();
// load the module with mock fs instead of real fs
// publish all the private state as an object
module = loadModule('./web-server.js', {fs: fsMock});
我强烈建议用这种方法编写单独的有效测试。只有验收测试才能击中整个堆栈。单元和集成测试应测试系统的隔离部分。
我认为嘲讽模式是一个很好的模式。也就是说,我通常选择将依赖关系作为参数发送给函数(类似于在构造函数中传递依赖关系)。
// foo.js
module.exports = function(dep1, dep2) {
return {
bar: function() {
// A function doing stuff with dep1 and dep2
}
}
}
当测试时,我可以发送模拟,空的对象,而不是看起来合适。请注意,我不这样做所有依赖关系,基本上只有IO - 我不觉得需要测试我的代码调用path.join
或其他任何。
我认为“低调”,也就是让你紧张是因为两件事情:
- 有人结构上类似于他们的代码来挖掘
- 有些人有他们自己的助手履行相同作为嘲笑等目标(这是一个非常简单的模块)
- 有些人不会单元测试这样的事情,而是旋转他们的应用程序(和数据库等)的实例和测试。更清洁的测试,服务器速度如此之快,不会影响测试性能。
总之,如果你认为嘲笑适合你,那就去吧!
的问题,这是单元测试更是创下这是不理想的数据库。 – 2012-06-03 11:10:50
@beck:只有当你在测试时发送一个真实的分贝。 – 2012-06-03 12:51:10
您可以轻松地嘲笑通过使用“一”要求:https://npmjs.org/package/a
//Example faking require('./foo') in unit test:
var fakeFoo = {};
var expectRequire = require('a').expectRequire;
expectRequire('./foo).return(fakeFoo);
//in sut:
var foo = require('./foo); //returns fakeFoo
感谢您的好评!然而,我有另一个问题: 我无法利用这种技术来覆盖被测模块中我自己定制函数的私有函数。它会产生两个函数:一个在本地范围内,另一个在全局范围内,被测模块始终调用全局/原始版本。 – Attilah 2014-12-13 23:24:00