どうも。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に強いエンジニアを募集しています。