我正在我的服务器上运行mocha测试,测试源脚本是一种独立的单元测试方式。
我正在测试的一个脚本调用Webpack的require.ensure
函数,这对于在Webpack捆绑时在应用程序中创建代码分割点很有用。
我为此脚本编写的测试不在Webpack上下文中运行,因此require.ensure
函数不存在,测试失败。
我试图为这个函数创建某种polyfill / stub / mock / spy,但是没有任何运气。
有一个包webpack-require,它允许创建webpack上下文。这可行,但速度慢得令人无法接受。我希望直接针对require.ensure
函数使用某种轻量级填充。
有什么建议吗? :)
这是一个非常基本的起点摩卡测试。
mocha测试加载一个设计模块,其中包含一个方法,如果定义了require.ensure
,该方法返回true。
foo.js
export default {
requireEnsureExists: () => {
return typeof require.ensure === 'function';
}
};
foo.test.js
import { expect } from 'chai';
describe('When requiring "foo"', () => {
let foo;
before(() => {
foo = require('./foo.js');
});
it('The requireEnsureExists() should be true', () => {
expect(foo.requireEnsureExists()).to.be.true;
});
});
答案 0 :(得分:5)
好的,经过大量的研究和审议,我终于得到了答案。
我最初认为我可以使用某种IoC / DI策略解决这个问题,但后来我找到负责加载模块的source code for Node JS's Module library。查看源代码,您会发现'要求'模块的函数(即我的例子中的foo.js)由_compile function of NodeJs's module loader创建。它是内部范围的,我无法看到修改它的直接机制。
我不太确定Webpack是如何或在何处扩展已创建的"要求"例如,但我怀疑它有一些黑魔法。我意识到我需要一些帮助来做一些类似的事情,并且不想编写大量复杂的代码来做这件事。
然后我偶然发现rewire ......
node.js应用程序的依赖注入。
rewire为模块添加了一个特殊的setter和getter,因此您可以修改它们的行为以进行更好的单元测试。你可以
- 为其他模块注入模拟
- 泄漏私人变量
- 覆盖模块中的变量。
- rewire不加载文件并评估内容以模拟节点的需求机制。实际上,它使用节点自己的要求来加载模块。因此,您的模块在测试环境中的行为与在常规情况下(除了您的修改)完全相同。
完美。我只需要访问私有变量。
安装重新布线后,让我的测试工作很简单:
<强> foo.js 强>
export default {
requireEnsureExists: () => {
return typeof require.ensure === 'function';
}
};
<强> foo.test.js 强>
import { expect } from 'chai';
import rewire from 'rewire';
describe('When requiring "foo"', () => {
let foo;
before(() => {
foo = rewire('./foo.js');
// Get the existing 'require' instance for our module.
let fooRequire = moduletest.__get__('require');
// Add an 'ensure' property to it.
fooRequire.ensure = (path) => {
// Do mocky/stubby stuff here.
};
// We don't need to set the 'require' again in our module, as the above
// is by reference.
});
it('The requireEnsureExists() should be true', () => {
expect(foo.requireEnsureExists()).to.be.true;
});
});
Aaaaah ......太开心了。再次快速运行测试土地。
哦,就我而言,它不需要,但如果您通过webpack捆绑代码进行基于浏览器的测试,那么您可能需要rewire-webpack插件。我也在某处读过这可能与ES6语法有关。
另一个注意事项:对于直接模拟require(...)语句,我建议使用mockery而不是重新连接。它没有重新连接那么强大(没有私有变量访问),但在我看来这有点安全。此外,它有一个非常有用的警告系统,可以帮助你不要做任何无意的嘲笑。
<强>更新强>
我也看到采用以下策略。在使用require.ensure
的每个模块中检查它是否存在,如果不存在则将其填充:
// Polyfill webpack require.ensure.
if (typeof require.ensure !== `function`) require.ensure = (d, c) => c(require);