【Typescript】axiosのmock【Jest】

Jestでaxiosをmockする方法

トリガーとしてわかりやすいようにフロントも一応書いています

プロダクト側(vue)

<template>
  <div>
    <Button @click="axiosGetMethods">axios Get</Button>
    <Button @click="axiosPostMethods">axios Post</Button>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import axios from 'axios'

export default Vue.extend({
  data(): {
    result: Object
  } {
    return {
      result: {},
    }
  },
  methods: {
    async axiosGetMethods() {
      const client = axios.create({
        baseURL: 'http://localhost:3000',
        headers: {
          'Content-Type': 'application/json',
        },
        responseType: 'json',
      })
      const response = await client.get('/get')
      this.result = response
    },
    async axiosPostMethods() {
      const client = axios.create({
        baseURL: 'http://localhost:3000',
        headers: {
          'Content-Type': 'application/json',
        },
        responseType: 'json',
      })
      const response = await client.post('/post', 'testparam')
      this.result = response
    },
  },
})
</script>

<style></style>

テストコード

import { shallowMount } from '@vue/test-utils'
import AxiosTestTarget from '@/pages/AxiosTestTarget.vue'
import flushPromises from 'flush-promises'
import axios from 'axios'
const createMock = axios.create({
  baseURL: 'http://localhost:3000',
  headers: {
    'Content-Type': 'application/json',
  },
  responseType: 'json',
})
jest.spyOn(axios, 'create').mockReturnValue(createMock)
const axiosGetSpy = jest.spyOn(createMock, 'get')
const axiosPostSpy = jest.spyOn(createMock, 'post')

describe('axiosのapi call test', () => {
  const wrapper = shallowMount(AxiosTestTarget)
  beforeEach(() => {
    axiosGetSpy.mockResolvedValue({ response: { testResponse: 'test' } })
    axiosPostSpy.mockResolvedValue({ response: { testResponse: 'test' } })
  })

  it('axios get', async () => {
    wrapper.findAll('Button').at(0).trigger('click')
    await flushPromises()
    expect(axiosGetSpy).toHaveBeenCalledWith('/get')
    expect(wrapper.vm.$data.result).toEqual({
      response: { testResponse: 'test' },
    })
  })
  it('axios post', () => {
    wrapper.findAll('Button').at(1).trigger('click')
    expect(axiosPostSpy).toHaveBeenCalledWith('/post', 'testparam')
    expect(wrapper.vm.$data.result).toEqual({
      response: { testResponse: 'test' },
    })
  })
})

上記はaxios.createをプロダクトコード内で行いでheadersの設定をため
テスト側では実際にaxios.createしている値を使い、それをjest.spyOnで返しています。(これがないとプロダクトコード側のaxios.createが出来なくてエラー)

const createMock = axios.create({
  baseURL: 'http://localhost:3000',
  headers: {
    'Content-Type': 'application/json',
  },
  responseType: 'json',
})
jest.spyOn(axios, 'create').mockReturnValue(createMock)

あとはbeforeEach側でmockで何を返すか指定してあげればOK

describe('axiosのapi call test', () => {
  const wrapper = shallowMount(AxiosTestTarget)
  beforeEach(() => {
    axiosGetSpy.mockResolvedValue({ response: { testResponse: 'test' } })
    axiosPostSpy.mockResolvedValue({ response: { testResponse: 'test' } })
  })

itの中ではmethodsのaxiosGetMethodsをトリガーするボタンをクリックしてあげる処理を記載する。
また、flushPromises()がないとテスト側でawaitすることが出来ず、即データを見に行ってしまう。あとは引数とaxios.getで返ってきた値(mockした値)がdataに入っているか確認して終了。 flushPromisesは別途npm installが必要です。

https://www.npmjs.com/package/flush-promises

wrapper.findAll(‘Button’).at(0).trigger(‘click’) await flushPromises() expect(axiosGetSpy).toHaveBeenCalledWith(‘/get’) expect(wrapper.vm.$data.result).toEqual({ response: { testResponse: ‘test’ }, })

axios.createってわざわざmockしたくないよね?

axios.createの外出しでaxiosの利用コードを少なくする

import axios from 'axios'
export const client = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: { 'X-Custom-Header': 'foobar' },
})
<template>
  <div>
    <Button @click="axiosGetMethods">axios Get</Button>
    <Button @click="axiosPostMethods">axios Post</Button>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import { client } from '@/userModules/axios.config'

export default Vue.extend({
  data(): {
    result: Object
  } {
    return {
      result: {},
    }
  },
  methods: {
    async axiosGetMethods() {
      const response = await client.get('/get')
      this.result = response
    },
    async axiosPostMethods() {
      const response = await client.post('/post', 'testparam')
      this.result = response
    },
  },
})
</script>

<style></style>
import { shallowMount } from '@vue/test-utils'
import AxiosTestTarget from '@/pages/AxiosTestTarget.vue'
import flushPromises from 'flush-promises'
import { client } from '@/userModules/axios.config'
const axiosGetSpy = jest.spyOn(client, 'get')
const axiosPostSpy = jest.spyOn(client, 'post')

describe('axiosのapi call test', () => {
  const wrapper = shallowMount(AxiosTestTarget)
  beforeEach(() => {
    axiosGetSpy.mockResolvedValue({ response: { testResponse: 'test' } })
    axiosPostSpy.mockResolvedValue({ response: { testResponse: 'test' } })
  })

  it('axios get', async () => {
    wrapper.findAll('Button').at(0).trigger('click')
    await flushPromises()
    expect(axiosGetSpy).toHaveBeenCalledWith('/get')
    expect(wrapper.vm.$data.result).toEqual({
      response: { testResponse: 'test' },
    })
  })
  it('axios post', () => {
    wrapper.findAll('Button').at(1).trigger('click')
    expect(axiosPostSpy).toHaveBeenCalledWith('/post', 'testparam')
    expect(wrapper.vm.$data.result).toEqual({
      response: { testResponse: 'test' },
    })
  })
})

プロダクト側はclient.getで
テスト側はjest.spyOn(client,’get’),jest.spyOn(client,’post’)でmock出来るようになりました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です