jest.fn() と jest.spyOn() の用法の違い - のこのこかずのこ

のこのこかずのこ

10年エンジニアやってるけどいまだになんもわからん

jest.fn() と jest.spyOn() の用法の違い

Jest で書かれた複雑なテストコードを読んでいると、 モック関数である jest.fn()jest.spyOn() の用法で混乱してしまうので、超シンプルなコードで要点を押さえておく。自分用メモ。

jest.fn()

test("jest.fn", () => {
    const mockFn = jest.fn();
    mockFn(1,2);  
    expect(mockFn).toHaveBeenCalledWith(1,2);
  });
  • 無からモック関数を生み出せる。
  • 適当なコールバック関数を指定したい時とかに便利。
  • .mockReturnValue() .mockImplementation() などで挙動のカスタマイズ可能。

jest.spyOn()

const obj = { add: (a: number, b: number): number => a + b };

test("spyOn", () => {
    const spy = jest.spyOn(obj, "add");
    obj.add(1,2);
    expect(spy).toHaveBeenCalledWith(1,2);
  });
  • 既存の関数(メソッド)を置き換える。ので、あくまでも元となる関数(メソッド)が必要。
  • スパイされた元の関数(メソッド)が呼び出されるたびに、その情報が記録される。基本的には監視目的として使う。
  • モックとして使いたい場合は、.mockImplementation()などで挙動のカスタマイズも可能。

ちなみに、importしたモジュールを spyOn したい場合は、 jest.mock()でモジュールをまるっとモック化する必要があるみたい。

import * as util from ".";

 jest.mock(".");   // これがないと TypeError: Cannot redefine property エラーになる

test("spyOn", () => {
    const spy = jest.spyOn(util, "add");
    util.add(1,2);
    expect(spy).toHaveBeenCalledWith(1,2);
  });