どうも。FF7、聖剣伝説3の両リメイクが待ち遠しい大庭です。
今回は、JavaScriptのテストツールのJestでのmockについての話です。
Jestでテスト書くのが初めてだったので、入門向けの話になりますのでご容赦を。
今回のテスト対象の擬似コード
こんな感じの関数(myFunc.js)をテストしたいとします。
const axios = require('axios') const function1 = require('./function1') const function2 = require('./function2') const function3 = require('./function3') module.exports = () => { const users = await axios.get('/users.json') const someResult = function1() let result if (someResult) { result = function2() } else { result = function3(users) } return { users: users, infos: result } }
この関数をテストするためにJestのmockをどう利用していくかを紹介していきます。
モジュールをmock化したい
自分で定義したfunction1や利用しているライブラリをmock化したい場合は下記のようにします。
jest.mock('./function1') jest.mock('axios')
このように記述するだけで、自動的にこれらを読み込んだ場合はmock化されます。
mockの戻り値を定義したい
mockの戻り値を定義したい場合は下記のように書きます。 (他の書き方もありますが
jest.mock('./function1', () => { return jest.fn(() => true); })
テストケースによってmockの戻り値を変えたい
これはもっといい書き方があるのではと思っているのですが、現状は下記のようにしています。
jest.mock('./function1') describe('function1', () => { it('case 1', () => { function1.mockReturnValue(true) expect(・・・) }) it('case 2', () => { function1.mockReturnValue(false) expect(・・・) }) })
Promiseを返す非同期関数の場合はmockResolvedValueを使います。
関数が呼ばれたかをチェックしたい
mock化するとtoBeCalledなどのマッチャーを利用することができるようになります。
const myFunc = require('./') jest.mock('axios') jest.mock('./function1') jest.mock('./function2') jest.mock('./function3) describe('myFunc', () => { it('case 1', () => { function1.mockReturnValue(true) myFunc() expect(function2).toBeCalled() expect(function3).not.toBeCalled() }) it('case 2', () => { function1.mockReturnValue(false) myFunc() expect(function2).not.toBeCalled() expect(function3).toBeCalled() }) })
さいごに
普段の開発ではRSpecを利用しているので、RSpecだったらこんな場合すぐ書けるのにJestだとどう書いたらいいんだー!!と初めの内は思っていましたが、慣れてくるとそこそこ書けるようになってきました。
Jestにはスナップショットなど他にも便利な機能があるようなので、早く「Jest、完全に理解した」と言えるように精進したいです。
あしたのチームではJestに強いエンジニアを募集しています。