1
1

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 1 year has passed since last update.

【備忘録】JestでのインターフェースとオブジェクトのMock実装方法について

Last updated at Posted at 2022-03-03

はじめに

jestでmockを使ったテストをすることになった際、色々記事を参考にしていたらなかなかうまくいかなかったため簡易的な備忘録としてうまくいった方法を残しておきます。

詳細説明などは下記記事の方が参考になるかとおもうので、先にこちらを読むことをお勧めします。

環境

  • node: 16.6.2
  • @types/jest: 27.0.3
  • jest: 27.4.5
  • ts-jest: 27.1.1
  • ts-node: 9.0.0
  • typescript: 4.0.2

前提

ClazzAのexecute関数で、TestRepositoryの各関数が何回呼ばれたかをテストしたい

  • ClazzA: 今回テストしたいクラス
  • TestRepository: ClazzAのインスタンス化に必要
  • 使用するExpect
    • 呼び出し回数のチェック:
      • expect(actual).toBeCalledTimes(n)
      • expect(actual).not.toBeCalled()
    • 引数のチェック(今回の記事では未使用):
      • expect(actual).toBeCalledWith()

実装方法

インターフェースを実装したMockを作成

Repository Interface の Mock を作成する

  1. jest.fn().mockReturnValue(返り値)
    任意の値を返すmock関数を作成する。

  2. jest.fn<Type, []>().mockImplementation(() => ();
    指定した型を返すmockを作成する。

  3. mockFn.mockClear();
    モックの使用履歴などをクリアする。テストを複数書く時にモック関数の呼び出し回数がどんどん加算されてしまわないようにしておく。

  4. 手順2で作成したモックをインスタンス化して、テストしたいクラスなどに渡す

import ClazzA from 'path/to/ClazzA';
import TestRepository from 'path/to/TestRepository';

describe("ClazzAのテスト", async () => {
  const executeMock = jest.fn().mockReturnValue(Promise.resolve());
  const Repository = jest.fn<TestRepository, []>().mockImplementation(() => ({
    execute: executeMock
  }));

  afterEach(() => {
    executeMock.mockClear();
  });

  test("executeMockが呼ばれるテスト", () => {
    const a = new ClazzA(new Repository());
    await a.execute();
		
    expect(executeMock).toBeCalledTimes(2);
  });
});

オブジェクトをモックする方法(spyOnを使用する)

TestRepositoryオブジェクトの Mock を作成する

  1. jest.spyOn();
    メソッドを使い、追跡したいメソッドを指定する

  2. (Clazz.prototype.method as jest.Mock).mockClear();
    モックの使用履歴をクリアしておく

  3. (Clazz.prototype.method as jest.Mock).mockImplementation();
    で返り値の指定などをしておく

  4. 手順2で作成したモックをインスタンス化して、テストしたいクラスなどに渡す

import ClazzA from 'path/to/ClazzA';
import TestRepository from 'path/to/TestRepository';

describe("ClazzAのテスト", async () => {
  beforeEach(() => {
    jest.spyOn(TestRepository.prototype, 'sampleMethod');
    jest.spyOn(TestRepository.prototype, 'testMethod');
  });
		
  afterEach(() => {
    (TestRepository.prototype.sampleMethod as jest.Mock).mockClear();
    (TestRepository.prototype.testMethod as jest.Mock).mockClear();
  });
		
  test("sampleMethod の返り値が0の時 testMethod が呼ばれないテスト", () => {
    (TestRepository.prototype.sampleMethod as jest.Mock).mockImplementation(() => {
      return 0;
    });
    const a = new ClazzA(new TestRepository());
    await a.execute();		 
    expect(TestRepository.prototype.testMethod).not.toBeCalled();
  });
});

おわりに

上記でインターフェースやオブジェクトをモック化することができました。
モック化するための記述量が多く、読み辛くなってしまうなあと感じたのでそのあたりを工夫していく必要がありそうです。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?