jest.spyOn()の基本的な使い方を確認してみた
こんにちは、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を作成する(=モックする)ことが出来ます。
下記はplay
Methodを持つ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のそれぞれをモックしてテストすることができます。
下記はplay
Methodを持つ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()
には明るくなかったので、今回確認できて良かったです。
以上