axios.createで作成したaxiosのラッパーを使ってテストする方法です。
もっと良いやり方があるよ!という場合はコメントいただけると幸いです。
ひとまずこれでテストはできます。モダンなやり方かはわかりませんのであしからず。
必要なライブラリ
- axios-mock-adapter
- vueのjestライブラリ達
テストコード
axiosのラッパーをインポート
import { axiosWrapper } from "@/domain/axios"
@/domain/axios
では、axiosWrapperをexportしています。
import axios from "axios"
export const axiosWrapper = axios.create({
baseURL: xxx,
timeout: 15000
...
})
axiosラッパーをモック化
axios-mock-adapterを利用して、ラッパーをモック化します。
const mockAxios = new MockAdapter(axiosWrapper)
モックの振る舞いを設定
getの場合
it("テストケース: get", async () => {
mockAxios.onGet(【URL】).reply(200, {})
...
})
URLの部分は、axios.createでbaseURLを設定していれば、baseURL以降のURLでOKです。
baseURLを設定していなければ、httpから始まるAPIのURLを指定する必要があるかと思います。
postの場合
it("テストケース: post", async () => {
mockAxios.onPost(【URL】).reply(200, {})
...
})
2本分のAPIをモック化する場合
同じ関数内で2本のAPIを呼んでいる場合等、2本分のAPIの戻り値を指定したい場合は、onXxxとreplyを繰り返します。
it("テストケース: API2本呼び出し", async () => {
mockAxios
.onGet(【URL1】).reply(200, {})
.onGet(【URL2】).reply(200, {})
...
})
同じAPIを呼び出し、1回目と2回目で戻り値を変えたい場合も同じやり方が使えます。その場合はreplyOnceを使うと良いです。
it("テストケース: 同じAPI2回呼び出し", async () => {
mockAxios
.onGet(【URL1】).replyOnce(400, {})
.onGet(【URL1】).replyOnce(200, {})
...
})
タイムアウトやネットワークエラーを戻り値とする
タイムアウトやネットワークエラー時のテストをしたい場合は、replyの部分をtimeoutやnetworkErrorOnceにします。
it("テストケース: タイムアウト", async () => {
mockAxios
.onGet(【URL】).timeout()
...
})
it("テストケース: ネットワークエラー", async () => {
mockAxios
.onGet(【URL】).networkErrorOnce()
...
})
結果の確認
何回呼ばれた?
history.getが配列になっているため、その配列数で呼ばれた数がわかります。
it("テストケース: API呼び出し回数", async () => {
mockAxios.onGet(【URL】).reply(200, {})
...
expect(mockAxios.history.get.length).toBe(2)
})
呼んだ時のリクエストは何か?
history.get[i]でそれぞれ取れます。
it("テストケース: get", async () => {
mockAxios.onGet(【URL】).reply(200, {})
...
// header
expect(mockAxios.history.get[0].header).toEqual({
token: "xxxxx"
})
// get parameter
expect(mockAxios.history.get[0].params).toEqual({
userId: "xxxxx"
})
})
it("テストケース: post", async () => {
mockAxios.onPost(【URL】).reply(200, {})
...
// header
expect(mockAxios.history.post[0].header).toEqual({
token: "xxxxx"
})
// post body
expect(JSON.parse(mockAxios.history.post[0].data)).toEqual({
userId: "xxxxx"
})
})
リセット
テストケース毎に、終了時にhistoryをリセットします。リセットしないとitを実行するたびにmockAxios.historyに溜まっていきます。
describe("テスト", () => {
afterEach(() => {
mockAxios.resetHistory()
})
})
蛇足
Axiosとは関係ありませんが、関数をモックしたい場合は以下のようにします。
import * as strUtils from "@/utils/strUtils"
jest.spyOn(strUtils, "isNull").mockReturnValue(false)
// promiseのresolveを返す関数の場合
jest.spyOn(strUtils, "isNull").mockResolvedValue("ok")
// promiseのrejectを返す関数の場合
jest.spyOn(strUtils, "isNull").mockRejectedValue("error")
jestのモックを使うときは、リセットを忘れずに。
describe("テスト", () => {
afterEach(() => {
jest.clearAllMocks()
})
})