如何对需要其他模块的Node.js模块进行单元测试,以及如何模拟全局require函数?
这是一个简单的示例,它说明了我的问题的症结所在:
This is a trivial example that illustrates the crux of my problem:
var innerLib = require('./path/to/innerLib');
function underTest() {
return innerLib.doComplexStuff();
}
module.exports = underTest;
我正在尝试为此代码编写单元测试.如何在不完全模拟require
函数的情况下模拟对innerLib
的需求?
I am trying to write a unit test for this code. How can I mock out the requirement for the innerLib
without mocking out the require
function entirely?
所以这是我试图模拟全局require
并发现即使这样做也不起作用:
So this is me trying to mock out the global require
and finding out that it won’t work even to do that:
var path = require('path'),
vm = require('vm'),
fs = require('fs'),
indexPath = path.join(__dirname, './underTest');
var globalRequire = require;
require = function(name) {
console.log('require: ' + name);
switch(name) {
case 'connect':
case indexPath:
return globalRequire(name);
break;
}
};
问题是underTest.js
文件中的require
函数实际上尚未被模拟.它仍然指向全局require
函数.因此,似乎只能模拟正在执行模拟的同一文件中的require
函数.如果我使用全局require
来包含任何内容,即使在覆盖本地副本之后,这些文件仍然需要全局require
引用.
The problem is that the require
function inside the underTest.js
file has actually not been mocked out. It still points to the global require
function. So it seems that I can only mock out the require
function within the same file I’m doing the mocking in. If I use the global require
to include anything, even after I’ve overridden the local copy, the files being required will still have the global require
reference.
您现在可以!
我发布了 proxyquire ,它将在测试模块时负责覆盖模块内部的全局需求.
I published proxyquire which will take care of overriding the global require inside your module while you are testing it.
这意味着您无需无需更改代码即可为所需模块注入模拟内容.
This means you need no changes to your code in order to inject mocks for required modules.
Proxyquire有一个非常简单的api,它可以解析您要测试的模块,并通过一个简单的步骤传递其所需模块的模拟/存根.
Proxyquire has a very simple api which allows resolving the module you are trying to test and pass along mocks/stubs for its required modules in one simple step.
@Raynos是正确的,传统上,您必须诉诸不太理想的解决方案才能实现该目标或进行自下而上的开发
@Raynos is right that traditionally you had to resort to not very ideal solutions in order to achieve that or do bottom-up development instead
这是我创建proxyquire的主要原因-允许自上而下的测试驱动开发而没有麻烦.
Which is the main reason why I created proxyquire - to allow top-down test driven development without any hassle.
请查看文档和示例,以判断它是否适合您的需求.
Have a look at the documentation and the examples in order to gauge if it will fit your needs.