69
53

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Jest で new Date() をモック化する

Last updated at Posted at 2020-07-11

JavaScript でアプリケーション開発をしていく際に、日付をつかさどる Date オブジェクトを使うことがちょくちょくあると思います。1

Date.now のようなメソッドをモック化することはとても簡単で、単に jest.fn() で置き換えてしまえばよいです。

Date.now = jest.fn(() => 1482363367071);

公式ドキュメントにもやり方が記載されています↓↓↓
2. Tests should be deterministic

しかし、Date は実行時によって値が変わってしまいますので、ちょっとテストではそのまま使うのは難しく、できれば Date をモック化して同じ時間を返してくれると色々都合が良いです。

サンプルコード2

まずはテスト対象ファイルのコードです。

datetime.js
const getTimestamp = () => new Date().getTime()
module.exports = getTimestamp

シンプルに Date オブジェクトのインスタンスを生成し、getTime() メソッドを実行してメソッド実行時のミリ秒を取得しています。そもそもこのメソッドならテストする必要なくない?という議論はあると思いますが、サンプルですのでご了承いただけると… :bow:

次に、こちらのファイルをテストするテストコードです。

datetime.test.js
import getTimestamp from './datetime'

const mockDate = new Date(1594374371110)
const spy = jest.spyOn(global, "Date")
                .mockImplementation(() => mockDate)
test('get timestamp', () => {
  const actual = getTimestamp()
  const expected = 1594374371110

  // ここはなくても良い
  expect(spy).toHaveBeenCalled()
  expect(actual).toBe(expected)

  // 初期化も忘れずに
  spy.mockReset()
  spy.mockRestore()
})

解説

一言で言ってしまうと、spyOn() メソッドを使った だけです。公式ドキュメントの spyOn() メソッドの説明を見た時「まさにこれやん」と思いました。

本記事の肝はこの3行ですね。説明のため、一部改行しています。

// ①
const mockDate = new Date(1594374371110)
const spy =
  // ②
  jest.spyOn(global, "Date")
      // ③
      .mockImplementation(() => mockDate)

①で Date オブジェクトのインスタンスを、モック用の固定した日付とセットで生成します。

②で spyOn メソッドを使い、グローバルオブジェクトの Date() メソッドに spyOn() メソッドでスパイするように設定しています。

③が最も重要な処理です。ここではスパイした後 mockImplementation() メソッドでレスポンスを指定しています。この処理がないと、new Date() を実行した場合のレスポンスは mockConstructor というモックオブジェクトになってしまい、getTime() メソッドが存在しない、というエラーが発生してしまいます。

ちなみにレスポンスを spy という変数に格納していますが、ここはなくても良いですが、私は spy 系のメソッドを使うならちゃんとコールされているよね?と言うことも確認したいため、受け取っています。

この処理により、datetime.js の getTimestamp() メソッド内で行っている new Date() は必ず同じ時間でインスタンスが生成されるようになります。誰かの参考になれば。

ではでは(=゚ω゚)ノ

P.S.

ちなみに以下の記事にもあるように jest-date-mock というモジュールを使うという Ultimate Solution もありますので、参考までに添付します。

JS の Date をテスト時にモックしたい(jest-date-mock の紹介)

  1. もちろん momentdayjs を使う場合は本記事は関係ないです。

  2. 今回のデモの環境については割愛します。Jest の公式ドキュメントのチュートリアル通りに作成しました。

69
53
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
69
53

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?