Jest + TypeSciptでaxiosを利用したコードのテスト

いい加減ちゃんと向き合わないと行けないときが来た気がしたので。非同期のモックテストをいろいろと試してみました。 axiosを使ったテスト HTTPリクエストでお世話になるaxiosで試します。 というシンプルなget関数 […]

広告ここから
広告ここまで

目次

    いい加減ちゃんと向き合わないと行けないときが来た気がしたので。非同期のモックテストをいろいろと試してみました。

    axiosを使ったテスト

    HTTPリクエストでお世話になるaxiosで試します。

    import axios from 'axios'
    
    export const get = async () => {
      return axios.get('https://wp-kyoto.cdn.rabify.me/wp-json')
    }

    というシンプルなget関数を用意します。

    jest.mockでaxiosをmockする

    axiosをjestでモックしてしまいます。mockResolvedValueでレスポンスを作れますが、TypeScriptでエラーがでますのでanyを噛ませます。

    import { get } from '../../libs/index'
    import axios from 'axios';
    
    jest.mock('axios');
    describe('first test', () => {
      afterEach(() => jest.restoreAllMocks())
      it('should return empty string', async () => {
        (axios.get as any).mockResolvedValue('')
        const data = await get()
        expect(data).toEqual('')
      })
    })

    jest.fnでaxios.getをmockする

    若干力技な気もしますが、以下のように書くことでjest.fnを使えます。

    import { get } from '../../libs/index'
    import axios from 'axios';
    
    describe('first test', () => {
      afterEach(() => jest.restoreAllMocks())
      it('should return empty string', async () => {    
        (axios.get as any) = jest.fn(async () => '')
        const data = await get()
        expect(data).toEqual('')
        expect(axios.get).toHaveBeenCalledTimes(1)
      })
    })

    こちらだとgetがコールされたかもテストできます。

    mockImplementationを使う

    mockResolvedValueを使うことで、jest.fnと同じことができる様子です。

    import { get } from '../../libs/index'
    import axios from 'axios';
    
    jest.mock('axios');
    describe('first test', () => {
      afterEach(() => jest.restoreAllMocks())
      it('should return empty string', async () => {
        (axios.get as any).mockImplementation(async () => 42)
        const data = await get()
        expect(data).toEqual(42)
        expect(axios.get).toHaveBeenCalledTimes(1)
      })
    })

    mockImplementationOnceを使うと、値を変えれる

    呼び出す回数によってレスポンスが変わる場合、Onceのほうを使うとよいです。

    import { get } from '../../libs/index'
    import axios from 'axios';
    
    jest.mock('axios');
    describe('first test', () => {
      beforeAll(() => {
        (axios.get as any).mockImplementationOnce(async () => 42)
          .mockImplementationOnce(async () => 24)
      })
      afterAll(() => jest.restoreAllMocks())
      it('should return empty string', async () => {
        const data = await get()
        expect(data).toEqual(42)
        expect(axios.get).toHaveBeenCalledTimes(1)
        const data1 = await get()
        expect(data1).toEqual(24)
        expect(axios.get).toHaveBeenCalledTimes(2)
      })
    })

    ちなみに定義した以上に呼び出すとmockImplementationの値が返ります。

    import { get } from '../../libs/index'
    import axios from 'axios';
    
    jest.mock('axios');
    describe('first test', () => {
      beforeAll(() => {
        (axios.get as any)
          .mockImplementation(async () => 1)
          .mockImplementationOnce(async () => 42)
          .mockImplementationOnce(async () => 24)
      })
      afterAll(() => jest.restoreAllMocks())
      it('should return empty string', async () => {
        const data = await get()
        expect(data).toEqual(42)
        expect(axios.get).toHaveBeenCalledTimes(1)
        const data1 = await get()
        expect(data1).toEqual(24)
        expect(axios.get).toHaveBeenCalledTimes(2)
        const data2 = await get()
        expect(data2).toEqual(1)
        expect(axios.get).toHaveBeenCalledTimes(3)
        const data3 = await get()
        expect(data3).toEqual(1)
        expect(axios.get).toHaveBeenCalledTimes(4)
      })
    })

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark