はじめに
axios
のようなHTTPリクエストを含む関数をテストする場合、テストの度にHTTPリクエストを行うと時間がかかったりサーバーに負荷がかかります。そのようなHTTPリクエストをモックすることで外部へのアクセスをすることなく、高速でテストが行えるようになります。
VitestではmockまたはspyOn関数で特定のメソッドをモックできます。mockはモジュール全体をモック、spyOnは特定のオブジェクトのメソッドをモックという違いはありますが、どちらでもモックできます。詳細を知りたい方は以下が参考になると思います。
モックする方法
ユーザー取得とユーザー作成をする関数です。これらで使用しているaxios
をモックします。
import axios from 'axios'
// ユーザーを取得する関数
export const fetchUsers = async () => {
return axios.get('/users').then((res) => res.data)
}
// ユーザーを作成する関数
export const createUser = async (user: { name: string }) => {
return axios.post('/users', user).then((res) => res.data)
}
mockを使用した場合
vi.mock('axios')
でaxiosをモックします。axios.get()
は非同期関数のためmockResolvedValue
で返り値を指定します。
import { it, vi, expect, beforeEach } from 'vitest'
import type { Mocked } from 'vitest'
import axios from 'axios'
import type { AxiosStatic } from 'axios'
import { fetchUsers, createUser } from './fetchers'
// axiosをモック
vi.mock('axios')
beforeEach(() => {
// モックをリセット
vi.resetAllMocks()
})
it('ユーザー取得のモック', async () => {
const mockData = [
{ id: 1, name: 'tarosuke' },
{ id: 2, name: 'momo' },
]
const mockedAxios = axios as Mocked<AxiosStatic>
// axiosのgetの返り値を指定
mockedAxios.get.mockResolvedValue({ data: mockData })
const users = await fetchUsers()
// 実行の引数を検証
expect(axios.get).toBeCalledWith('/users')
// 取得した値が同じか検証
expect(users).toEqual(mockData)
})
it('ユーザー作成のモック', async () => {
const mockData = { name: 'pac' }
const mockedAxios = axios as Mocked<AxiosStatic>
// axiosのpostの返り値を指定
mockedAxios.post.mockResolvedValue({ data: mockData })
const user = await createUser(mockData)
// 実行の引数を検証
expect(axios.post).toBeCalledWith('/users', mockData)
// 取得した値が同じか検証
expect(user).toEqual(mockData)
})
spyOnを使用した場合
vi.spyOn(axios, 'get')
でaxiosのgetをモックします。axios.get()
は非同期関数のため、こちらも同じくmockResolvedValue
で返り値を指定します。
import { it, vi, expect, beforeEach } from 'vitest'
import axios from 'axios'
import { fetchUsers, createUser } from './fetchers'
beforeEach(() => {
// モックをリセット
vi.resetAllMocks()
})
it('ユーザー取得のモック', async () => {
const mockData = [
{ id: 1, name: 'tarosuke' },
{ id: 2, name: 'momo' },
]
// axiosのgetの返り値を指定
vi.spyOn(axios, 'get').mockResolvedValue({ data: mockData })
const users = await fetchUsers()
// 実行の引数を検証
expect(axios.get).toBeCalledWith('/users')
// 取得した値が同じか検証
expect(users).toEqual(mockData)
})
it('ユーザー作成のモック', async () => {
const mockData = { name: 'pac' }
// axiosのpostの返り値を指定
vi.spyOn(axios, 'post').mockResolvedValue({ data: mockData })
const user = await createUser(mockData)
// 実行の引数を検証
expect(axios.post).toBeCalledWith('/users', mockData)
// 取得した値が同じか検証
expect(user).toEqual(mockData)
})
まとめ
Vitestでaxiosをモックする方法をご紹介しました。mockとspyOnのどちらでもモックできますが、個人的にはspyOnの方がコード量が少なく済むため好みです。
最後に
GoQSystemでは一緒に働いてくれる仲間を募集中です!
ご興味がある方は以下リンクよりご確認ください。