使用webpack的require.ensure函数为javascript模块编写testing
我在我的服务器上运行摩卡testing,testing源脚本是一种单独的unit testing方式。
我正在testing的一个脚本调用了Webpack的require.ensure
函数,这个函数在被Webpack绑定的时候在应用程序中创build代码分割点是非常有用的。
我为这个脚本编写的testing不在Webpack上下文中运行,因此require.ensure
函数不存在,testing失败。
我试图为这个函数创build一些polyfill / stub / mock / spy,但是没有任何运气。
有一个包, webpack-require ,它允许创build一个webpack上下文。 这可以工作,但速度慢得令人难以接受。 我宁愿有一些直接针对require.ensure
函数的轻量级require.ensure
。
任何build议? 🙂
这是一个非常基本的摩卡testing起点。
摩卡testing加载一个包含方法的人工模块,如果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; }); });
好的,经过多方研究和思考,我终于得到了答案。
我最初以为我可以使用某种IoC / DI策略来解决这个问题,但是后来我find了负责加载模块的Node JS的模块库的源代码 。 看看源代码,你会注意到模块的'require'函数(例如我的例子中的foo.js )是由NodeJs的模块加载器的_compile函数创build的。 它的内部范围,我看不到一个即时修改它的机制。
我不太确定Webpack如何或在哪里扩展创build的“require”实例,但我怀疑这是一些黑魔法。 我意识到,我需要一些帮助来做类似的事情,而不想写一大堆复杂的代码来这样做。
然后我偶然发现了…
node.js应用程序的dependency injection。
rewire增加了一个特殊的setter和getter模块,所以你可以修改他们的行为,以更好的unit testing。 你可以
- 注入其他模块的模拟
- 泄漏私有variables
- 覆盖模块内的variables。
- 重新连接不加载文件并评估内容以模拟节点的需求机制。 实际上它使用节点自己的要求来加载模块。 因此,您的模块在testing环境中的行为与正常情况下的行为完全相同(除了您的修改)。
完善。 访问私有variables是我所需要的。
安装rewire后,让我的testing工作很容易:
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 ….太高兴了。 快速运行testing土地。
哦,在我的情况下,这是不需要的,但如果你是通过webpack绑定你的代码的基于浏览器的testing,那么你可能需要rewire-webpack插件。 我也读过这个地方,这可能有ES6语法的问题。
另外一个注意事项:为了直接嘲弄require(…)语句,我build议使用嘲讽而不是rewire。 它不像rewire那么强大(没有私有variables访问),但是在我看来这更安全一些。 此外,它有一个非常有用的警告系统,以帮助您不要做任何无意的嘲弄。
更新
我也看到了以下战略正在被采用。 在使用require.ensure
每个模块中,检查它是否存在,如果不是,则require.ensure
它:
// Polyfill webpack require.ensure. if (typeof require.ensure !== `function`) require.ensure = (d, c) => c(require);
- 使用摩卡与TDD接口,ReferenceError
- 摩卡是如何做没有幻影的DOMtesting
- 如何testing用sinon.spy调用的socket.io事件
- 如何在node.js模块中正确导出variables,以使其在unit testing中可见
- Webdriver(wd)testing在本地工作,但超时Travis CI?
- 使用Mocha生成节点应用程序testing和LCOV报告
- MochaJS:如何在testing之间共享断言/“它('应该')”代码
- nodejs / mocha / nock – 模拟整个html响应
- 摩卡testing:未捕获TypeError:无法读取null的属性“状态”