JS/TS のユニットテストで axios をモックするのになんとなくmoxiosを使っていたが、やめようかなという話
理由は
- moxios が 3 年以上更新されていない
- Issues の返信や Dependabot のプルリクも放置されているっぽい
moxios.stubRequest
した axios のリクエストがたまに返ってこない時がある- ある特定の URL で
moxios.stubRequest(URL, ...
だと Jest から axios を実行した際、then に入ってこない時があるので、moxios.stubRequest(new RegExp(URL), ...
という謎対応で回避している - この辺のコードが怪しいけど、調べてない
- ある特定の URL で
- そもそも moxios のような高機能なライブラリは必要なさそうなテストケースだった
- axios が
Promise.resolve
かPromise.reject
を返すようにモック化すれば、テストケース的には事足りる
- axios が
テストフレームワークに Jest を使っているので、Jest のモック機能だけでいけそう
また、1 つの関数内で複数回 axios を実行したりしていないので、テストコードが複雑になることもないと思う
Jest のモック機能へ移行
以下の 2 行でaxios.get
がPromise.resolve
を返すようにモックできる
jest.mock('axios') axios.get.mockResolvedValue({ data: { name: 'test' } })
JS ならこれでオッケー、ただし TS だとaxios.get
に mockResolvedValue は存在しないので、エラーになる
以下のようにすればエラーも消えて、型推論も効くようになる
;(axios as jest.Mocked<typeof axios>).get.mockResolvedValue({ data: { name: 'test' } })
Jest の設定
毎回モック設定を書くのは冗長なので、以下の設定をしておく
// test/unit/setup.ts import axios from 'axios' jest.mock('axios') export default axios as jest.Mocked<typeof axios>
// jest.config.js setupFiles: ['<rootDir>/test/unit/setup.ts'],
setupFiles にテストを実行する前に実行してほしい処理を書いておく
// テストコード import mockAxios from '@test/setup' // Promise.resolve mockAxios.get.mockResolvedValue({ data: { name: 'test' } }) // Promise.reject mockAxios.get.mockRejectedValue({ response: { status: 400 } })
また、moxios.wait
を使って非同期処理を調整していた場合、すべてasync/await
などに置き換える必要がある
moxios.wait
は内部的に setTimeout 関数を呼んでいるだけなので、そもそもasync/await
に置き換えた方がよい