LoginSignup
23
11

コードで理解。jest.mock()、jest.spyOn()、jest.fn()の違い。

Posted at

jestについて勉強を進めていると、
とても多くの「これは何?」に出会います。

今回は私が理解しづらかった

jest.spyOnjest.fnjest.mock について見ていきます

jest.spyOn()って何?

jest.spyOnは、特定のオブジェクトのメソッドをモックに置き換える ために使用されます。
元のメソッドの呼び出しを監視(spy)しつつ、必要に応じてモックの実装を提供することができます。

const obj = {
  method: () => 'こんにちわ',
};

const spy = jest.spyOn(obj, 'method'); // obj.method()を監視下として設定

obj.method(); // 使われるとそれが記録されます

expect(spy.mock.calls).toHaveLength(1); // 1度呼び出した

obj.method();

expect(spy.mock.calls).toHaveLength(2); // 2度呼び出した

mockRestore メソッドを使うと、オリジナル関数に戻すことができます。
「ここではモック化したい」「こっちは戻して使いたい」といったことが可能となります。

describe('radome', () => {
  let spy: any;

  afterEach(() => {
    spy.mockRestore(); // testが終わる毎に元へ戻す
    // jest.resotreAllMopcks() // mockした全ての関数を元に戻すことも可能
  });
  it('randomを100固定', () => {
    // Math.random()は100を返す
    // モック関数の戻り値を変更するには、mockImplementationを利用します
    spy = jest.spyOn(Math, 'random').mockImplementation(() => 100);
    expect(Math.random()).toBe(100);
  });

  // ↓このままだとこけます。spyが見当たらず、初期化できないため。
  // afterEac内を spy && spy.mockRestore() で囲めば動く
  it('not random', () => {
    expect(Math.random()).toBeLessThan(1); // 1未満である
  });
});

jest.fn()って何?

jest.fnは新しいモック関数を作成するために使用されます。モック関数はテスト中に呼び出された回数や引数を記録するほか、任意の実装を提供することもできます。

const mockFn = jest.fn(); // とりあえずmockFnというのは関数だよと設定する。 

mockFn('Hello', 'World'); // モック関数を呼び出す、適当に引数を持たせてみる

// モック関数が一度呼ばれたことを確認
expect(mockFn).toHaveBeenCalledTimes(1);
// expect(mockFn.mock.calls).toHaveLength(1); これも一緒

// モック関数が指定した引数で呼ばれたことを確認
expect(mockFn).toHaveBeenCalledWith('Hello', 'World');

jest.mockって何?

jest.mockは、モジュール全体をまるごとモックに置き換える ために使用されます。
モジュール全体をモックに置き換えるので、そのモジュールが提供するすべての関数やオブジェクトを制御下に置くことができます。


// good.ts
export const good = (): number => {
  return Math.floor(Math.random() * 10);
};
export const bad = (): string => {
  return "bad";
};

// goodjob.ts
import { good } from './seed';
export const goodjob = () => {
  return `${good()}点です`;
};

// goodjob.test.ts
import { goodjob } from './goodjob';
jest.mock('./good', () => { // good.tsを丸っとmock化
  return {
    good: jest // その中のgood.tsのgood関数をモック化
      .fn()
      .mockImplementationOnce(() => 100) // 1度目は100を返す
      .mockImplementationOnce(() => 10), // 2度目は10を返す
    bad: jest // bad関数もモック化
      .fn(()=> "ハズレです") // モックで強制的にreturnするテキストを変更している
  };
});

test('テスト名', () => {
  // goodjob関数の中で呼ばれているgoodは100を返す
  expect(godjob()).toBe('100点です'); 
  // goodjob関数の中で呼ばれているgoodは10を返す
  expect(godjob()).toBe('10点です');
});

jest.spyOn() 、 jest.fn() 、 jest.mock()の違い

  • jest.spyOn
    • 特定のオブジェクトのメソッドをモックに置き換えて監視する(実際に存在するメソッドを指定すればOK)
    • アプリケーションに実在する関数の動きをチェックしたい時に使えます。
  • jest.fn
    • 新しいモック関数を作成する
    • callback用として適当な関数を用意する時に使えますね。
  • jest.mock
    • モジュール全体をモックに置き換える。
    • 外部のAPIとかを使ってテストしたい時に使えますね(axiosとか)
23
11
0

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
23
11