2023.04.07[Fri]

JestでspyOn関数を使って、windowをモックする方法

  • Javascript
  • TypeScript

目次

  • - はじめに
  • - 環境
  • - 実装
  • - jest.spyOnについて
  • - jest.spyOnを使ってwindowをモック
  • - 実行結果
  • - 注意点
  • - まとめ

はじめに

こんにちは、Webエンジニアの柴田です。
今回はJestでwindowをモックする方法をご紹介します。
windowをモックすることで、windowを使ったスクロールのテストやwindowのリサイズのテストなどが可能になります。

環境

Jest: 27.5.1
TypeScript: 4.6.4

実装

jest.spyOnについて

元の関数の実装をモック関数で上書きするだけでなく、元の実装を残したまま、対象の関数を監視することができる関数です。

jest.spyOnを使ってwindowをモック

まず、windowをモックする変数を定義します。
モック方法はJestspyOn関数を使います。

// 第三引数が'get'の理由は、windowオブジェクトのgetメソッドをモックしたいため
const windowSpy = jest.spyOn(window, 'window', 'get');

今回はなぜjest.spyOnを採用したのか?
元の関数の実装を追跡して、元の関数で呼ばれたどうかを含めたテストを想定して実装するためです。

またmockImplementation関数を使い、windowSpyにモック処理を追加することもできます。 mockImplementation関数は、元の実装をモックで上書き実装する関数です。
例えば、windowのスクロールやリサイズのモック処理を追加してみます。

windowSpy.mockImplementation(() => ({
   scrollTo: () => jest.fn(),
   ResizeObserver: jest.fn().mockImplementation(() => ({
     disconnect: jest.fn(),
     observe: jest.fn(),
 }))
}) as unknown as Window & typeof globalThis);

実際にテストを書いて、windowをモックできたかを確認しましょう。
スクロールできたかどうかを確認するテストを書きます。

describe('windowのモック テスト', () => {
  test('windowのscrollTo関数が呼ばれているかどうかテスト', () => {
    // モックをセット
    const windowSpy = jest.spyOn(window, 'window', 'get');

    windowSpy.mockImplementation(() => ({
      scrollTo: () => jest.fn(),
      ResizeObserver: jest.fn().mockImplementation(() => ({
        disconnect: jest.fn(),
        observe: jest.fn(),
      }))
    }) as unknown as Window & typeof globalThis);

    // スクロール
    window.scrollTo();

    // 呼ばれたかどうかCheck
    expect(windowSpy).toHaveBeenCalled();
    // 呼ばれた回数もCheck
    expect(windowSpy).toHaveBeenCalledTimes(1);

    // リセット処理
    windowSpy.mockRestore();
  });
});

実行結果

無事テストが通りました。

補足

jest.fnjest.spyOnの違いと使い分け

・違い
jest.fn 元の関数の実装をモック関数で上書きする関数
jest.spyOn 元の関数の実装をモック関数で上書きするだけでなく、元の実装を残したまま、対象の関数を監視することができる関数

・使い分け
jest.fnを使う場合、テスト時に関数の元の実装を意識しなくて良い場合
jest.spyOnを使う場合、元の実装を残したまま監視したい場合やテストごとにモックした関数の実装を元に戻したい場合

注意点

モックのクリーンアップの記述を忘れずに書きましょう。
他のテストの結果に影響を与えないためです。

mockRestore()関数を使い、モックを元の実装に戻します。

mockRestore()
jest.spyOn()によって作成したモックを元の値に戻す関数になります。

windowSpy.mockRestore();

まとめ

以上、JestでspyOn関数を使って、windowをモックする方法をご紹介しました。

今回記事で紹介したコードのフルバージョン
describe('windowのモック テスト', () => {
  test('windowのscrollTo関数が呼ばれているかどうかテスト', () => {
    // モックをセット
    const windowSpy = jest.spyOn(window, 'window', 'get');

    windowSpy.mockImplementation(() => ({
      scrollTo: () => jest.fn(),
      ResizeObserver: jest.fn().mockImplementation(() => ({
        disconnect: jest.fn(),
        observe: jest.fn(),
      }))
    }) as unknown as Window & typeof globalThis);

    // スクロール
    window.scrollTo();

    // 呼ばれたかどうかCheck
    expect(windowSpy).toHaveBeenCalled();
    // 呼ばれた回数もCheck
    expect(windowSpy).toHaveBeenCalledTimes(1);

    // リセット処理
    windowSpy.mockRestore();
  });
});

Share

Shopify アクセスモードの オフラインとオンラインを同時に使用するPageSpeedInsightsをAPIで実行する