如何使用ES6模块模拟unit testing的依赖关系
我试图摆弄Ecmascript 6模块使用webpack + traceur transpile到ES5 CommonJS,但我有麻烦成功地unit testing他们。
我尝试使用Jest + traceur预处理器,但automocking和依赖项名称似乎变得棘手,加上我似乎无法得到sourceMaps与Jest和节点检查器debugging工作。
unit testingES6模块有更好的框架吗?
我已经开始在我的testing中使用import * as obj
样式,它将一个模块的所有输出作为一个对象的属性导入,然后可以被模拟。 我发现这比使用rewire或者proxyquire或者其他类似的技术要干净得多。
我不能为traceur这个问题提供框架,但是我发现这个与我的Karma,Jasmine和Babel的设置一起工作,我在这里发布,因为这似乎是最受欢迎的这种types的问题。
当我需要模拟Redux动作时,我经常使用这个策略。 这是一个简短的例子:
import * as exports from 'module-you-want-to-mock'; import SystemUnderTest from 'module-that-uses-above-module'; describe('your module', () => { beforeEach(() => { spyOn(exports, 'someNamedExport'); // mock a named export spyOn(exports, 'default'); // mock the default export }); // ... now the above functions are mocked });
我实际上是通过删除Jest并使用Karma + Jasmine + Webpack并使用https://github.com/jhnns/rewire来模拟依赖;
如果您正在使用Webpack,另一个比rewire灵活性更高的选项是inject-loader 。
例如,在与Webpack捆绑在一起的testing中:
describe('when an alert is dismissed', () => { // Override Alert as we need to mock dependencies for these tests let Alert, mockPubSub beforeEach(() => { mockPubSub = {} Alert = require('inject!./alert')({ 'pubsub-js': mockPubSub }).Alert }) it('should publish \'app.clearalerts\'', () => { mockPubSub.publish = jasmine.createSpy() [...] expect(mockPubSub.publish).toHaveBeenCalled() }) })
注入 – 加载,以类似的方式proxyquire至less允许注入依赖关系在导入之前,而在rewire你必须先导入,然后rewire这使得嘲笑一些组件(如有一些初始化)是不可能的。
嗨,你可以使用proxyquire:
import assert from 'assert'; import sinon from 'sinon'; import Proxyquire from 'proxyquire'; let proxyquire = Proxyquire.noCallThru(), pathModelLoader = './model_loader'; describe('ModelLoader module.', () => { it('Should load all models.', () => { let fs, modelLoader, ModelLoader, spy, path; fs = { readdirSync(path) { return ['user.js']; } }; path = { parse(data) { return {name: 'user'}; } }; ModelLoader = proxyquire(pathModelLoader, {'fs': fs, 'path': path}); modelLoader = new ModelLoader.default(); spy = sinon.spy(modelLoader, 'loadModels'); modelLoader.loadModels(); assert(spy.called); }); });
Proxyquire会帮助你,但是它不会用现代的webpack + ES6模块,即“别名”。
import fs from 'fs'; import reducers from 'core/reducers'; ... proxyquire('../module1', { 'fs': mockFs, // this gonna work 'core/reducers': mockReducers // what about this? });
that
不行。 只要你可以嘲笑fs – 你不能嘲笑减速器。 在任何webpack或者babel转换之后,你必须指定依赖的real
名称。 通常 – 名称相对于模块1的位置。 可能是'../../../shared/core/reducers'。 也许不会。
有解决scheme – https://github.com/theKashey/proxyquire-webpack-alias (基于fork的proxyquire稳定)或https://github.com/theKashey/resolveQuire (不太稳定,可以运行原始的代理)
他们两个都工作得很好,并且会用一种简单的方式嘲笑任何ES6模块(这是一个很好的方法)(这是一个好方法)