ctr*_*usb 1 javascript unit-testing mocha.js node.js webpack
我在我的服务器上运行mocha测试,测试源脚本是一种独立的单元测试方式.
我正在测试的一个脚本调用Webpack的require.ensure函数,这对于在Webpack捆绑时在应用程序中创建代码分割点很有用.
我为此脚本编写的测试不在Webpack上下文中运行,因此该require.ensure函数不存在,并且测试失败.
我试图为这个函数创建一些polyfill/stub/mock/spy但是没有任何运气.
有一个包,webpack-require,它允许创建webpack上下文.这可行,但速度慢得令人无法接受.我希望有一种require.ensure直接针对该功能的轻量级polyfill .
有什么建议?:)
这是一个非常基本的起点摩卡测试.
mocha测试加载一个包含一个方法的人工模块,如果require.ensure定义了该方法则返回true .
foo.js
export default {
requireEnsureExists: () => {
return typeof require.ensure === 'function';
}
};
Run Code Online (Sandbox Code Playgroud)
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;
});
});
Run Code Online (Sandbox Code Playgroud)
好的,经过大量的研究和考虑,我终于得到了答案.
我最初认为我可以使用某种IoC/DI策略来解决这个问题,但后来我找到了Node JS的Module库的源代码,它负责加载模块.查看源代码,您会注意到模块的'require'函数(即我的示例中的foo.js)是由NodeJs模块加载器的_compile函数创建的.它是内部范围的,我无法看到修改它的直接机制.
我不太确定Webpack是如何或在哪里扩展创建的"require"实例,但我怀疑它有一些黑魔法.我意识到我需要一些帮助来做类似性质的事情,并且不想写一大堆复杂的代码来做到这一点.
然后我偶然发现了重新布线 ......
node.js应用程序的依赖注入.
rewire为模块添加了一个特殊的setter和getter,因此您可以修改它们的行为以进行更好的单元测试.你可以
- 为其他模块注入模拟
- 泄漏私有变量
- 覆盖模块中的变量.
- 重新连接不会加载文件并评估内容以模拟节点的需求机制.实际上它使用节点自己的require来加载模块.因此,您的模块在测试环境中的行为与在常规情况下(除了您的修改)完全相同.
完善.访问私有变量就是我所需要的.
安装重新布线后,让我的测试工作很简单:
foo.js
export default {
requireEnsureExists: () => {
return typeof require.ensure === 'function';
}
};
Run Code Online (Sandbox Code Playgroud)
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;
});
});
Run Code Online (Sandbox Code Playgroud)
Aaaaah ......太开心了.快速运行测试土地了.
哦,在我的情况下它不需要,但如果你通过webpack捆绑代码进行基于浏览器的测试,那么你可能需要rewire-webpack插件.我还在某处读到这可能与ES6语法有问题.
另一个注意事项:对于直接模拟require(...)语句,我建议使用mockery而不是重新连接.它没有重新连接那么强大(没有私有变量访问),但在我看来这有点安全.此外,它有一个非常有用的警告系统,以帮助您不做任何无意的嘲笑.
更新
我也看到了采用以下策略.在每个使用require.ensure检查它存在的模块中,如果不存在则将其填充:
// Polyfill webpack require.ensure.
if (typeof require.ensure !== `function`) require.ensure = (d, c) => c(require);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2169 次 |
| 最近记录: |