jest.spyOn()の基本的な使い方を確認してみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部 IoT事業部の若槻です。
JavaScriptのテスティングフレームワークJestでは、テスト対象のModuleやFunctionのモックを作成するためのJest Objectがいくつか用意されています。
今回は、そのJest Objectのうちのjest.spyOn()の基本的な使い方を確認してみました。
確認してみた
確認を実施した環境は次の通りです。
npm ls jest typescript --depth=0 hoge-project@0.1.0 ├── jest@26.6.3 └── typescript@3.9.10
jest.spyOn(object, methodName)
jest.spyOn(object, methodName)を使用すると、Methodを含んだObjectのmock functionを作成する(=モックする)ことが出来ます。
下記はplayMethodを持つvideoをモックしているテスト例です。
export const video = {
play() {
return true;
},
};
import { video } from '../video';
test('plays video true', () => {
const spy = jest.spyOn(video, 'play');
const isPlaying = video.play();
expect(spy).toHaveBeenCalled();
expect(isPlaying).toBe(true);
spy.mockRestore();
});
テストを実行すると成功しました。
$ npx jest test/video.test.ts PASS test/video.test.ts ✓ plays video true (2 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 5.011 s Ran all test suites matching /test\/video.test.ts/i.
またjest.spyOn(object, methodName).mockImplementation(() => customImplementation)のように使用すればMethodを上書きして戻り値を任意の値に指定することもできます。
test('plays video false', () => {
const spy = jest.spyOn(video, 'play').mockImplementation(() => false);
const isPlaying = video.play();
expect(spy).toHaveBeenCalled();
expect(isPlaying).toBe(false);
spy.mockRestore();
});
テストを実行すると成功しました。
$ npx jest test/video.test.ts PASS test/video.test.ts (5.252 s) ✓ plays video true (2 ms) ✓ plays video false (1 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 5.296 s Ran all test suites matching /test\/video.test.ts/i.
Methodの上書きは、認証や外部への接続が必要となるMethodのテストで役に立ちそうですね。
jest.fn()との比較
前述したjest.spyOnでのMethodの戻り値の上書きは、jest.fn()を使用した場合にも行えます。
比較のために同じvideoをjest.fn()でモックしてみます。mockReturnValue()を使用します。
test('plays videos false jest.fn()', () => {
(video.play as jest.Mock) = jest.fn().mockReturnValue(false);
const isPlaying = video.play();
expect(video.play).toHaveBeenCalled();
expect(isPlaying).toBe(false);
});
テストを実行すると成功しました。
$ npx jest test/video.test.ts PASS test/video.test.ts (5.449 s) ✓ plays video true (2 ms) ✓ plays video false (1 ms) ✓ plays videos false jest.fn() Test Suites: 1 passed, 1 total Tests: 3 passed, 3 total Snapshots: 0 total Time: 5.508 s, estimated 6 s Ran all test suites matching /test\/video.test.ts/i.
jest.spyOn(object, methodName, accessType?)
Methodはgetterまたはsetterのいずれかを指定することができますが、spyOnの第三引数accessTypeでgetまたはsetを指定すれば、getterとsetterのそれぞれをモックしてテストすることができます。
下記はplayMethodを持つvideoをモックしているテスト例です。
export const video = {
// it's a getter!
get play() {
return true;
},
};
export const audio = {
_volume: 0,
// it's a setter!
set volume(value) {
this._volume = value;
},
get volume() {
return this._volume;
},
};
import { video, audio } from '../video_and_audio';
test('plays video', () => {
const spy = jest.spyOn(video, 'play', 'get'); // we pass 'get'
const isPlaying = video.play;
expect(spy).toHaveBeenCalled();
expect(isPlaying).toBe(true);
spy.mockRestore();
});
test('plays audio', () => {
const spy = jest.spyOn(audio, 'volume', 'set'); // we pass 'set'
audio.volume = 100;
expect(spy).toHaveBeenCalled();
expect(audio.volume).toBe(100);
spy.mockRestore();
});
テストを実行すると成功しました。
npx jest test/video_and_audio.test.ts PASS test/video_and_audio.test.ts (5.647 s) ✓ plays video (3 ms) ✓ plays audio Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 5.705 s Ran all test suites matching /test\/video_and_audio.test.ts/i.
setterやgetterをテストしたい場合はjest.spyOn()が役に立ちそうですね。
おわりに
jest.spyOn()の基本的な使い方を確認してみました。
今までテスト時のモックはjest.fn()を使うことがほとんどでjest.spyOn()には明るくなかったので、今回確認できて良かったです。
以上







