如何使用ES6模块模拟单元测试的依赖关系

时间:2014-12-05 19:10:57

标签: javascript unit-testing ecmascript-6 traceur jestjs

我试图使用webpack + traceur来调试Ecmascript 6模块以转换为ES5 CommonJS,但是我无法成功地对它们进行单元测试。

我尝试使用Jest + traceur预处理器,但自动插件和依赖项名称似乎变得棘手,而且我似乎无法让sourceMaps与Jest和节点检查器调试一起使用。

是否有更好的单元测试ES6模块框架?

5 个答案:

答案 0 :(得分:51)

我在我的测试中开始使用import * as obj样式,它将模块中的所有导出作为对象的属性导入,然后可以对其进行模拟。我发现这比使用重新布线或代理或任何类似技术更清洁。

我无法代表问题所使用的框架traceur,但我发现这与我的Karma,Jasmine和Babel的设置一起使用,我发布了它这里似乎是这种类型中最受欢迎的问题。

在需要模拟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
});

答案 1 :(得分:6)

如果您使用的是Webpack,那么另一个选项比{re}更具灵活性inject-loader

例如,在与Webpack捆绑在一起的测试中:

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类似,至少允许一个人在导入之前注入依赖关系,而在重新连接时你必须首先导入然后重新连接,这使得模拟一些组件(例如那些有一些初始化的组件)是不可能的。

答案 2 :(得分:5)

我实际上是通过删除Jest并使用Karma + Jasmine + Webpack并使用https://github.com/jhnns/rewire来模拟依赖项来实现此目的

答案 3 :(得分:5)

您好,您可以使用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);
    });
});

答案 4 :(得分:1)

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依赖关系的名称。通常 - 相对于module1位置的名称。可能是' ../../../ shared / core / redurs'。可能不是。

解决方案有所下降 - https://github.com/theKashey/proxyquire-webpack-alias(稳定,基于代理商的分支)或https://github.com/theKashey/resolveQuire(不太稳定,可以在原始代理查询中运行)

它们都可以工作,并且会以一种代理方式模拟任何ES6模块(它们都很好)(这是一种好方法)