下記の関数があるとしましょう。
1 | function calcDuration(date: string) { |
この関数のテストを書くのに、注意しなければいけないことが1点あります。もう気づいたと思いますが、new Date()
の結果を固定値にしないと、テストの結果が実行時の日付に依存してしまいますので、環境依存が発生し許容できないでしょう。Jestにはモジュールモックを含め、いくつのやり方がありますが、標準ビルトインオブジェクトかつコンストラクタの場合、どうモックするか、ドキュメントには詳しく書かれませんでした。ウェブで検索してみた結果、jest.spyOn(global, 'Date')
という感じで書くのは一番直感的で柔軟性が高いと感じました。よって、テストのコードはこうなるかと思います。
1 | test("mock", () => { |
しかし、上記のコードの実行結果は[Jest] Expected value to be (using Object.is): 4, Received: 0
というエラーになるでしょう。理由は簡単です。calcDuration
関数内でDate
コンストラクタは二回も呼ばれ、そして常にdateToUse
が返ってきます。よって、差分が0になるのは正しい振る舞いです。そこを修正する為に、mockImplementation
にて条件分岐を作ればシンプルに解決できます。引数が空の場合dateToUse
を返し、それ以外は元々のビルドインオブジェクトを使わせます。結果は下記の感じです。
1 | test("mock", () => { |
他にmockImplementationOnce
でやる方法も考えられますが、実装を意識しないと書けなさそうと思いましたので、上記のやり方を採用することにしました。