✨
jest で孫モジュールだけモックしたい!
例えば: React のコンポーネントのテストで、そのコンポーネントが使っているモジュールをモックしたいときなど
解決方法
各種モジュール(@testing-library/react
や react
など)を再インポートする
実例
import { render } from '@testing-library/react';
import { Component } from './Component';
describe('Component', () => {
test('without mock', () => {
render(<Component />);
});
jest.isolateModules(() => {
const { render } = require('@testing-library/react'); // 再インポートする
jest.mock('./dateModule', () => ({ now: () => 42 }));
const { Component } = require('./Component');
test('mocking module that Component uses', () => {
render(<Component />);
});
jest.unmock('./dateModule');
});
jest.isolateModules(() => {
const { render } = require('@testing-library/react'); // 再インポートする
jest.mock('./dateModule', () => ({ now: () => 42 }));
const { Component } = require('./Component');
test('mocking module that Component uses', () => {
render(<Component />);
});
jest.unmock('./dateModule');
});
});
react-testing-library を 再 import しないと、Component が読み込んでいる react と react-testing-library でズレが生じて、You might have more than one copy of React
とエラーが出るはずです。
jest.isolateModules とは
jest は 各モジュールをキャッシュしています。つまり、require した時に同じオブジェクトが返ってきます。
expect(require('./moduleA')).toBe(require('./moduleA')); // どのモジュールでも成立する
isolateModules は、新しいモジュールのキャッシュを持ったサンドボックスを生成します。
import { Component } from './Component';
import React from 'react';
test('check equality',() => {
expect(Component).toBe(require('./Component').Component); // 等しい
expect(React).toBe(require('react')); // 等しい
jest.isolateModules(() => {
expect(Component).not.toBe(require('./Component').Component); // 等しくない
expect(React).not.toBe(require('react')); // 等しくない
});
});
Discussion