60

我正在尝试使用 webpack + traceur 来处理 Ecmascript 6 模块以转换为 ES5 CommonJS,但我无法成功对它们进行单元测试。

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

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

4

5 回答 5

58

我已经开始import * as obj在我的测试中使用这种风格,它将模块中的所有导出作为对象的属性导入,然后可以对其进行模拟。我发现这比使用 rewire 或 proxyquire 或任何类似技术要干净得多。

我不能代表问题中使用的框架 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
});
于 2016-07-16T18:14:40.447 回答
7

如果您使用的是 Webpack,另一个比 rewire 更灵活的选项是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()
  })
})

inject-loader,以类似于proxyquire 的方式至少允许一个人在导入之前注入依赖项,而在rewire 中,您必须先导入然后rewire,这使得模拟某些组件(例如那些具有一些初始化的组件)变得不可能。

于 2016-03-21T11:44:01.277 回答
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);
    });
});
于 2016-08-31T19:57:58.953 回答
4

实际上,我通过放弃 Jest 并使用 Karma + Jasmine + Webpack 并使用https://github.com/jhnns/rewire来模拟依赖项来实现这一点

于 2015-07-30T18:09:14.227 回答
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/reducers”。也许不吧。

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

它们都可以正常工作,并且会以代理查询方式模拟任何 ES6 模块(它们非常好)(这是一个好方法)

于 2017-05-23T22:12:29.323 回答