この記事の概要
new Date()
はテスト時には固定の値を返して欲しいのでその方法を記載した簡易メモ
方法1:useFakeTimers, setSystemTimeを使う
const mockDate = new Date(2021, 0, 1, 1, 1, 1);
jest.useFakeTimers();
jest.setSystemTime(mockDate);
Jest公式通りの多分一番簡単なベストな方法
https://jestjs.io/ja/docs/timer-mocks
【追記】
非同期処理が入っているとreactのコンポーネント生成が終わる前にDOMの判定をしてしまったり、Timeoutになってしまったりします。
その場合は
.useFakeTimers({
doNotFake: [
"nextTick",
"setImmediate",
"clearImmediate",
"setInterval",
"clearInterval",
"setTimeout",
"clearTimeout",
],
})
と記述すると直ります
参考: https://github.com/nock/nock/issues/2200#issuecomment-1280957462
なので個人的に方法2の方が良いのではないかと思えてきました・・
※@types/jest
のversionが古いとdoNotFake
指定できません
方法2:globalのDateにspy
const mockDate = new Date(2021, 1, 2, 2, 2, 2);
const spy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate);
※dayjsも内部ではnew Dateしているので、mock化できます
※@types/jest
のversionが古い場合はmockDate as unknown as string
※Date.now()を使っている箇所があるとエラーになるので方法1にした方が良いかもしれません
方法3:spy用の関数を別途用意
export function getNow() {
return new Date();
}
import * as DateUtils from './date-utils';
const mockDate = new Date(2021, 2, 3, 3, 3, 3);
const spy = jest.spyOn(DateUtils, 'getNow').mockReturnValue(mockDate);
※new Date()
を使うのはgetNow()
だけ。他は全てgetNow()
を使わないといけない
ひと手間かかるけど個別のテストごとに値変えて確認する時などに割と便利
その他
Math.random()
の固定化も上記2、3の感じでイケる
https://stackoverflow.com/questions/41570273/how-to-test-a-function-that-output-is-random-using-jest
コード全体、バージョン情報等はこちら
https://github.com/yamatoto/jest-sample
https://github.com/yamatoto/jest-sample/tree/master/src/views/clock