我试着使用webpack + traceur将Ecmascript 6模块转译为ES5 CommonJS格式,但是我在进行单元测试时遇到了困难。
我尝试使用Jest + traceur预处理器,但是自动模拟和依赖项名称似乎出现了问题,而且我无法在Jest和node-inspector调试中使用sourceMaps。
是否有更好的框架来进行ES6模块的单元测试?
我试着使用webpack + traceur将Ecmascript 6模块转译为ES5 CommonJS格式,但是我在进行单元测试时遇到了困难。
我尝试使用Jest + traceur预处理器,但是自动模拟和依赖项名称似乎出现了问题,而且我无法在Jest和node-inspector调试中使用sourceMaps。
是否有更好的框架来进行ES6模块的单元测试?
我已经开始在我的测试中使用import * as obj
的语法,它会将模块中所有导出作为对象的属性导入,然后可以对其进行模拟。相比使用Rewire或Proxyquire等类似技术,我认为这样做更加简洁。
关于使用traceur框架的问题,我无法发表意见。但是,我在Karma、Jasmine和Babel的环境下实现了这个方法,并且将其发布在这里,因为这似乎是这种问题中最受欢迎的。
当需要模拟Redux actions时,我经常使用这种策略。以下是一个简短的示例:
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
});
import {someExport} from module
符号。 - markyphdescribe
块。不过如果不了解你特定的设置,很难确定。 - carpeliamsinon.sandbox
可以防止你的模拟数据影响到其他测试。 - carpeliamdescribe('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类似的是,inject-loader允许在导入之前注入依赖项,而在rewire中必须先导入再重写,这使得对某些组件(例如那些具有某些初始化的组件)进行模拟变得不可能。
require
而不是import .. as ..
语法。 - alwerequire
和ES6导入。唯一需要require
的地方是在测试本身中模拟依赖项。 - djskinnerkarma.config.js
(如果您使用的话还有webpack.config
文件)。提前感谢。 - Jon P Smithnpm i inject-loader
然后 require(inject!...)
即可。 - djskinner您可以使用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);
});
});
我实际上通过放弃Jest,改用Karma + Jasmine + Webpack,并使用https://github.com/jhnns/rewire来模拟依赖项,使这一切都能够工作。
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?
});
那
行不通。只要您可以模拟fs-您无法模拟reducers。
在任何webpack或babel转换之后,您必须指定依赖项的real
名称。通常是相对于module1位置的名称。可能是'../../../shared/core/reducers'。也可能不是。
有https://github.com/theKashey/proxyquire-webpack-alias(稳定,基于proxyquire分支)或https://github.com/theKashey/resolveQuire(不太稳定,可以在原始proxyquire上运行)的解决方案。
两者都很有效,并且将以proxyquire方式(这是一个好方法)模拟任何ES6模块(它们非常好)。