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;
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?
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;
}
};
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.
如果您曾经使用过jest,那么您可能对jest的模拟功能很熟悉。
使用“ jest.mock(...)”,您可以简单地在代码中的某处的需求语句中指定将出现的字符串,并且每当需要使用该字符串的模块时,都将返回一个模拟对象。
例如
会用您从该“工厂”功能返回的对象完全替换“ firebase-admin”的所有导入/要求。
好吧,您可以在使用jest时执行此操作,因为jest会在它运行的每个模块周围创建一个运行时,并将“挂钩”版本的require注入到模块中,但是如果没有jest,您将无法执行此操作。
我试图通过模拟需求来实现这一点,但对我而言,它不适用于源代码中的嵌套级别。看看github上的以下问题:并非总是用Mocha调用mock-require。
为了解决这个问题,我创建了两个npm模块,您可以使用它们来实现所需的功能。
您需要一个babel插件和一个模块模拟程序。
在您的.babelrc中,使用带有以下选项的babel-plugin-mock-require插件:
并在测试文件中使用jestlike-mock模块,如下所示:
该
jestlike-mock
模块仍然非常初级,并且没有很多文档,但是也没有太多代码。我感谢任何PR提供了更完整的功能集。目标是重新创建整个“ jest.mock”功能。为了了解jest如何实现,可以在“ jest-runtime”包中查找代码。例如,请参见https://github.com/facebook/jest/blob/master/packages/jest-runtime/src/index.js#L734,此处它们生成模块的“自动模拟”。
希望能有所帮助;)