はじめに
jest.isolateModules(fn) を利用すると、モジュールの振る舞いをテストケース内に閉じ込め、テストごとに独立した試験をすることが可能になります。
使い所としては、process.env
の値によって振る舞いが変わるモジュールのテストなどで便利です。
サンプルとして、 jestで現在時刻を固定化する で使った Date
オブジェクトがテストケース内で固有のものになるようにしてみます。12
使い方
const moment = require('moment')
// 固定したい時間
const MOCKED_TIME = '2019/8/1 12:00:00';
describe('モックした現在時刻のテスト', () => {
// setup
const OriginalDate = Date; // 退避
const now = new OriginalDate(MOCKED_TIME);
beforeEach(()=> {
// 各テストケースの中では固有のDateにする
jest.isolateModules(() => {
// Date.now() と new Date() のみmocking
Date.now = jest.fn().mockReturnValue(now.valueOf());
jest.spyOn(global, 'Date').mockImplementation((arg) => {
if (arg === 0 || arg) {
return new OriginalDate(arg);
}
return now;
});
});
});
afterAll(() => {
jest.restoreAllMocks();
});
test('現在時刻をYYYY/MM/DDの形式で表示できる', () => {
const actual = moment().format('YYYY/MM/DD');
expect(actual).toBe('2019/08/01');
});
test('Dateコンストラクタで現在時刻が固定化される', () => {
const actual = new Date();
expect(actual.valueOf()).toBe(now.valueOf());
});
test('Dateコンストラクタで時刻を指定できる', () => {
const actual = new Date(0);
expect(actual.valueOf()).toBe(0);
});
})
describe('現在時刻がモックオブジェクトになっていないことのテスト', () => {
test(`現在時刻は${MOCKED_TIME}ではない`, () => {
const now = new Date();
expect(now).not.toBe(new Date(MOCKED_TIME));
expect(moment(now).format('YYYY/MM/DD HH:mm:ss')).not.toBe(MOCKED_TIME);
});
})
-
jest.spyOn
で作成したモックはrestoreAllMocks
ではもとに戻せない が、試験終了後に mockFn.mockRestore() を呼ぶようにするとこのサンプルと同じことが可能です ↩