JestのクラスのモックをTypeScriptで使用する
- 2021.03.14
- TypeScript
TypeScriptのプロジェクトで、Jestを使ってテストを書いているのですが、基本的なクラスのモックの使い方や、モックのメソッドに渡された引数のチェックのしかたが最初わからなかったので、動作するようになった結果をメモ。
前提として、Service層とRepository層にレイヤ分けされた構造において、Repository層のクラスをモックにして、Service層のテストをしたい場合を想定しています。
TypeScriptにおけるJestのクラスのモックの使い方
公式ドキュメントに記載の通り、jest.mock('./モック化したいクラスのパス')
と記載することで、指定したクラスをモック化できます。ただ、これを記載しただけだとすべてのメソッドを、常に undefined
を返すモック関数に置き換えるので、メソッド呼び出しを行うテストでは、mockImplementation()
メソッドを使って、メソッドの動作を指定する必要があります。
この時、公式ドキュメントの通り、以下の記載を行おうとすると、SoundPlayer.mockImplementation
の箇所でTypeScriptに怒られます(Property ‘mockImplementation’ does not exist on type)。
import SoundPlayer from './sound-player';
jest.mock('./sound-player');
describe('テスト', () => {
beforeAll(() => {
SoundPlayer.mockImplementation(() => {
return {
playSoundFile: () => {
return "test"
},
};
});
});
});
これについては、SoundPlayer as jest.Mock
のように、Mock型にキャストすることで回避しました(もしかするともっと良い方法があるのかもしれません)。
import SoundPlayer from './sound-player';
jest.mock('./sound-player');
const SoundPlayerMock = SoundPlayer as jest.Mock; // 追加
describe('テスト', () => {
beforeAll(() => {
// SoundPlayerMockに変更
SoundPlayerMock.mockImplementation(() => {
return {
playSoundFile: () => {
return "test"
},
};
});
});
});
モックのメソッドに渡された引数のチェックのしかた
次は、モックをスパイする方法についてです。公式ドキュメントに以下の記載があるのですが、私はこれを試してみてもダメでした。
メソッドの呼び出しは
theAutomaticMock.mock.instances[index].methodName.mock.calls
に保存されます。
どうしたかというと、以下のようにmockImplementationメソッドで定義する関数を、モック関数で定義するようにしました。
const mockFunc = jest.fn(() => {
return "test";
});
mockImplementationの呼び出し箇所を以下に修正
SoundPlayerMock.mockImplementation(() => {
return {
playSoundFile: mockFunc,
};
});
こうすることで、mockFunc.mock.calls[0][0]で、モック関数に渡された引数を取得することができました。モック関数の使い方の詳細はこちらを参照ください。
-
前の記事
AmplifyでデプロイしたECSのコンテナで環境変数を使用する 2021.02.16
-
次の記事
Serverless FrameworkでAppSyncを開発する 2021.03.24