首页 > 解决方案 > 在 Vue 应用程序中模拟 axios 以进行前端测试

问题描述

在测试我的 Vue 应用程序的前端时,我有时想跳过与 API 后端的通信。

我想出了以下想法:

axios.post(...)简单的方法是在每次调用or之前添加一个检查axios.get(...),但我不想在我编写的每个 api 函数中添加代码。所以我考虑过使用interceptorsaxios 的,但我认为不可能停止请求,只返回模拟数据,对吧?

然后我考虑包装 axios,并动态返回真实的 axios 实例或模拟的 axios 实例,它还实现了基于 Store 状态的所有其他 axios 函数.post().get()我想过这样的事情(我正在使用 TypeScript):

import store from '@/vuex-store'

const axios = Axios.create( // real store config );
const axiosMock = {
  get(path: string) {
    if (path == '/test') {
      return Promise.resolve( // mocked data );
    }

    return Promise.resolve(true)
  }
}

class AxiosWrapper {
  get instance() {
    if (store.state.skipServerCommunication) {
      return axiosMock;
    }

    return axios
  }
}

export default new AxiosWrapper();

但是这个解决方案有一些问题:

  1. 我需要将所有 axios 调用替换为axiosWrapper.instance.get(...). 我可以以某种方式避免这种情况并以我仍然可以使用的方式模拟 axiosaxios.get(...)吗?
  2. VSCode 无法再提供自动补全功能,因为返回的实例要么是 typeAxiosStatic要么"MyMockType". 所以我考虑实现AxiosStatic接口,但由于接口中有两个匿名函数,我很难正确地做到这一点AxiosInstance。有没有其他方法可以克服这个问题?

标签: javascripttypescriptvue.jsaxios

解决方案


改为使用axios-mock-adapter。您可以axios根据需要使用高级匹配模式模拟每个测试的调用。

示例用法:

import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'

describe('UserList', () => {
  it('gets users on mount', async () => {
    const mock = MockAdapter(axios)
    mock.onGet('/users').reply(200, {
      users: [{ id: 1, name: 'John Smith' }],
    })

    const wrapper = shallowMount(UserList)
    await wrapper.find('.getUsersBtn').trigger('click')
    expect(wrapper.vm.users[0].id).toBe(1)
  })
})

推荐阅读