这是一个微不足道的例子,说明了我的问题的症结所在:
var innerLib = require('./path/to/innerLib');
function underTest() {
return innerLib.doComplexStuff();
}
module.exports = underTest;
我正在试着为这段代码写一个单元测试。如何在不完全模拟require
函数的情况下模拟出对innerLib
的需求?
所以这是我试图模拟全局require
,发现它甚至不能工作:
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
引用。
发布于 2013-05-01 04:04:47
在这种情况下,更好的选择是模拟返回的模块的方法。
不管是好是坏,大多数node.js模块都是单例的;需要()相同模块的两段代码会得到对该模块的相同引用。
您可以利用这一点,并使用诸如sinon之类的东西来模拟所需的项。mocha测试如下:
// in your testfile
var innerLib = require('./path/to/innerLib');
var underTest = require('./path/to/underTest');
var sinon = require('sinon');
describe("underTest", function() {
it("does something", function() {
sinon.stub(innerLib, 'toCrazyCrap').callsFake(function() {
// whatever you would like innerLib.toCrazyCrap to do under test
});
underTest();
sinon.assert.calledOnce(innerLib.toCrazyCrap); // sinon assertion
innerLib.toCrazyCrap.restore(); // restore original functionality
});
});
Sinon具有用于进行断言的良好integration with chai,并且我向integrate sinon with mocha编写了一个模块以允许更容易地进行间谍/存根清理(以避免测试污染)。
注意,不能以同样的方式模拟underTest,因为underTest只返回一个函数。
另一种选择是使用Jest mock。在their page上跟进
发布于 2017-07-15 00:48:37
我使用mock-require。确保在对要测试的模块执行require
操作之前定义了模拟。
发布于 2017-12-12 23:38:43
嘲笑require
对我来说就像是一个讨厌的黑客。我个人会尽量避免这种情况,并重构代码以使其更具可测试性。有多种方法来处理依赖关系。
1)将依赖项作为参数传递
function underTest(innerLib) {
return innerLib.doComplexStuff();
}
这将使代码具有普遍的可测试性。缺点是您需要传递依赖项,这会使代码看起来更复杂。
2)将模块实现为类,然后使用类方法/属性获取依赖关系
(这是一个人为的例子,其中类的使用是不合理的,但它传达了这个想法) (ES6例子)
const innerLib = require('./path/to/innerLib')
class underTestClass {
getInnerLib () {
return innerLib
}
underTestMethod () {
return this.getInnerLib().doComplexStuff()
}
}
现在,您可以轻松地使用存根getInnerLib
方法来测试代码。代码变得更加冗长,但也更容易测试。
https://stackoverflow.com/questions/5747035
复制相似问题