web-dev-qa-db-ja.com

ES6モジュールを使用した単体テストの依存関係を模擬する方法

Webpack + traceurを使用してEcmascript 6モジュールをいじってES5 CommonJSに移行しようとしていますが、ユニットテストを正常に実行できません。

Jest +トレーサープリプロセッサを使用してみましたが、自動モックと依存関係の名前はおかしくなり、さらにsourceMapsをJestとノードインスペクターのデバッグで動作させることができません。

ES6モジュールを単体テストするためのより良いフレームワークはありますか?

56
Evan Layman

Jestを削除してKarma + Jasmine + Webpackを使用し、 https://github.com/jhnns/rewire を使用して依存関係をモックすることで、実際にこれを機能させました

5
Evan Layman

私はテスト内でimport * as objスタイルの使用を開始しました。これは、モジュールからのすべてのエクスポートをオブジェクトのプロパティとしてインポートし、それをモックすることができます。これは、rewireやproxyquireなどの手法を使用するよりもずっときれいだと思います。

私は質問で使用されたフレームワークであるトレーサーについて話すことはできませんが、これはカルマ、ジャスミン、バベルのセットアップで動作することがわかりました。これが最も人気があるようですので、ここに投稿していますこのタイプの質問。

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
});
52
carpeliam

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する必要があります。

6
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);
    });
});
5
JinVillaz

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 (安定性が低く、元のproxyquireで実行できます)

両方とも同様に機能し、ES6モジュール(それらは非常に優れています)をproxyquire方法でモックします(それは良い方法です)

1
Anton Korzunov