1. ホーム
  2. javascript

[解決済み] Jestで同じモジュール内の関数をモックするには?

2023-01-23 20:45:38

質問

次の例を正しくモック化するための最良の方法は何でしょうか?

問題は、インポート時間後に foo は元のモック解除された bar .

module.js :

export function bar () {
    return 'bar';
}

export function foo () {
    return `I am foo. bar is ${bar()}`;
}

module.test.js :

import * as module from '../src/module';

describe('module', () => {
    let barSpy;

    beforeEach(() => {
        barSpy = jest.spyOn(
            module,
            'bar'
        ).mockImplementation(jest.fn());
    });


    afterEach(() => {
        barSpy.mockRestore();
    });

    it('foo', () => {
        console.log(jest.isMockFunction(module.bar)); // outputs true

        module.bar.mockReturnValue('fake bar');

        console.log(module.bar()); // outputs 'fake bar';

        expect(module.foo()).toEqual('I am foo. bar is fake bar');
        /**
         * does not work! we get the following:
         *
         *  Expected value to equal:
         *    "I am foo. bar is fake bar"
         *  Received:
         *    "I am foo. bar is bar"
         */
    });
});

変えることができた。

export function foo () {
    return `I am foo. bar is ${bar()}`;
}

になります。

export function foo () {
    return `I am foo. bar is ${exports.bar()}`;
}

というのがありますが、これはどこでもやるにはかなり醜いと私は思います。

どのように解決するのですか?

紆余曲折を経て、私がたどり着いた解決策は 依存性注入 に、デフォルトの引数を設定することです。

というわけで、私なら

export function bar () {
    return 'bar';
}

export function foo () {
    return `I am foo. bar is ${bar()}`;
}

から

export function bar () {
    return 'bar';
}

export function foo (_bar = bar) {
    return `I am foo. bar is ${_bar()}`;
}

これは私のコンポーネントのAPIを壊すような変更ではないので、以下のようにすることで簡単にバーを上書きすることができます。

import { foo, bar } from '../src/module';

describe('module', () => {
    it('foo', () => {
        const dummyBar = jest.fn().mockReturnValue('fake bar');
        expect(foo(dummyBar)).toEqual('I am foo. bar is fake bar');
    });
});

これはテストコードも少しきれいになるという利点があります :)