追記
timer-mocks を使ってください。
- https://jestjs.io/ja/docs/timer-mocks
- https://jestjs.io/ja/docs/jest-object#jestsetsystemtimenow-number--date
afterEach(() => {
jest.useRealTimers();
});
test('', () => {
const fixed = new Date('2022-1-1T00:00:00');
jest.useFakeTimers().setSystemTime(fixed.getTime());
// ...
});
以下の情報は古いです。
はじめに
時間に依存しているようなAPIの振る舞いを試験するとき、現在時刻を固定化して試験したいことがよくあると思います。
Date.now()
と new Date()
をモックすることで、現在時刻を固定化することができます!!
やり方
Date
の振る舞いを固定することで、moment()
の現在時刻も固定化できます。
const moment = require('moment')
describe('モックした現在時刻のテスト', () => {
let now;
let spiedDate;
// setup
beforeAll(() => {
const OriginalDate = Date; // 退避
now = new OriginalDate('2019/8/1 12:00:00');
// Date.now() と new Date() のみmocking
Date.now = jest.fn().mockReturnValue(now.valueOf());
spiedDate = jest.spyOn(global, 'Date').mockImplementation((arg) => {
if (arg === 0 || arg) {
return new OriginalDate(arg);
}
return now;
});
});
afterAll(() => {
spiedDate.mockRestore();
});
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);
});
})
説明
ここで固定したい日付を設定します。
後ほどコンストラクタの振る舞いを書き換えるため、Date
オブジェクトを退避しています。
const OriginalDate = Date; // 退避
now = new OriginalDate('2019/8/1 12:00:00');
Date.now() を固定し、常に同じUnix時刻が返却されるようにしています。
Date.now = jest.fn().mockReturnValue(now.valueOf());
jest.spyOn を利用して、コンストラクタで固定の値を返却するようにします。
arg === 0
の判定は、Unix時間0の時も正しく動作させるためです。
spiedDate = jest.spyOn(global, 'Date').mockImplementation((arg) => {
if (arg === 0 || arg) {
return new OriginalDate(arg);
}
return now;
});
Date
オブジェクトを元に戻します。(global.Date = OriginalDate
でも同じ効果)
afterAll(() => {
spiedDate.mockRestore();
});