web-dev-qa-db-ja.com

Jest:デフォルトと名前付きエクスポートの両方を備えたモックES6モジュール

デフォルトと名前付きエクスポートの両方を備えたES6モジュールがあります。

/** /src/dependency.js **/

export function utilityFunction() { return false; }

export default function mainFunction() { return 'foo'; }

2番目のES6モジュールで使用されています。

/** /src/myModule.js **/

import mainFunction, { utilityFunction } from './dependency';

// EDIT: Fixed syntax error in code sample
// export default myModule() {
export default function myModule() {
    if (!utilityFunction()) return 2;
    return mainFunction();
}

Jestを使用してmyModule.jsの単体テストを記述しようとしています。しかし、名前付きインポートとデフォルトインポートの両方をモックしようとすると、Jestは名前付きインポートのみをモックするように見えます。既定のインポートの実際の実装を引き続き使用し、.mockImplementation()を呼び出した後でも、それをモックすることはできません。これが私が使用しようとしているコードです:

/** 
  * Trying to mock both named and default import. 
  * THIS DOESN'T WORK.
  */

/** /tests/myModule.test.js **/

import mainFunction, { utilityFunction } from '../src/dependency';
import myModule from '../src/myModule';

jest.mock('../src/dependency');

mainFunction.mockImplementation(() => 1);
utilityFunction.mockImplementation(() => true);

describe('myModule', () => {
    it('should return the return value of mainFunction when the result of utilityFunction is true', () => {
        expect(myModule()).toEqual(1); // FAILS - actual result is 'foo'
    });
});

この動作は私には本当に奇妙に思われます。なぜなら、JUSTのデフォルトインポートまたはJUSTの名前付きインポートをモックすると、このAPIは正常に動作するからです。たとえば、myModule.jsがデフォルトのインポートのみをインポートする場合、これは非常に簡単に実行できます。

/**
  * Trying to mock just the default import. 
  * THIS WORKS.
  */

/** /src/myModule.js **/

import mainFunction from './dependency';

// EDIT: Fixed syntax error in code sample
// export default myModule() {
export default function myModule() {
    return mainFunction();
}


/** /tests/myModule.test.js **/
// If only mainFunction is used by myModule.js

import mainFunction from '../src/dependency';
import myModule from '../src/myModule';

jest.mock('../src/dependency');
mainFunction.mockImplementation(() => 1);

describe('myModule', () => {
    it('should return the return value of mainFunction', () => {
        expect(myModule()).toEqual(1); // Passes
    });
});

名前付きの 'utilityFunction'エクスポートのみが使用される場合、インポートのモックも非常に簡単です。

/**
  * Trying to mock both named and default import. 
  * THIS WORKS.
  */
/** /src/myModule.js **/

import { utililtyFunction } from './dependency';

// EDIT: Fixed syntax error in code sample
// export default myModule()
export default function myModule() {
    return utilityFunction();
}


/** /tests/myModule.test.js **/
// If only utilityFunction is used by myModule.js

import { utilityFunction } from '../src/dependency';
import myModule from '../src/myModule';

jest.mock('../src/dependency);
utilityFunction.mockImplementation(() => 'bar');

describe('myModule', () => {
    it('should return the return value of utilityFunction', () => {
        expect(myModule()).toEqual('bar'); // Passes
    });
});

Jestを使用して名前付きインポートとデフォルトインポートの両方をモックすることは可能ですか?モジュールから名前付き値とデフォルト値の両方をインポートし、両方をモックできる、私が望む結果を達成するために使用できる別の構文はありますか?

10
bean

構文エラーがあります... myModule.jsのデフォルトのエクスポートからfunctionキーワードが省略されています。次のようになります。

import mainFunction, { utilityFunction } from './dependency';

export default function myModule() {
    if (!utilityFunction()) return 2;
    return mainFunction();
}

それ以外の方法でテストを実行する方法はわかりませんが、ローカルで試してみましたが、成功しました。

2
djfdev

他の解決策は私にとってはうまくいきませんでした。これは私がやった方法です:

  jest.mock('../src/dependency', () => ({
    __esModule: true,
    utilityFunction: 'utilityFunction',
    default: 'mainFunction'
  }));

それを行う別の方法:

jest.unmock('../src/dependency');

const myModule = require('../src/dependency');
myModule.utilityFunction = 'your mock'
11
Albert Olivé