首页 > 解决方案 > 用 Jest 模拟 axios 和拦截器返回 mockImplementation undefined

问题描述

我有这个 axios 实现:

const api = axios.create({
    baseURL: process.env.REACT_APP_BACKEND_URL,
    headers: {
        "content-type": "application/json"
    },
    responseType: "json"
})

function createAxiosRequestInterceptor(axiosInstance) {
    axiosInstance.interceptors.request.use(
        config => {
            const accessToken = localStorage.getItem(REACT_FE_ACCESS_TOKEN)
            if (accessToken) {
                config.headers.common.Authorization = `Bearer ${accessToken}`
            }
            return config
        }
    )
}

function createAxiosResponseInterceptor(axiosInstance) {
    axiosInstance.interceptors.response.use(
        response => {
            return response;
        },
        error => {
            return Promise.reject(error)
        }
    )
}

这是我的测试:

import React from 'react'
import { Router } from 'react-router-dom'
import { cleanup, render, wait } from '@testing-library/react'
import { createMemoryHistory } from 'history'
import axios from 'axios'
import Dashboard from '../../pages/Dashboard'
import AuthRouter from '../../../AuthRouter'
import thunk from 'redux-thunk';
import configureMockStore from 'redux-mock-store';

function renderWithRouter(
  ui,
  {
    route = '/',
    history = createMemoryHistory({ initialEntries: [route] }),
  } = {}
) {
    const middlewares = [thunk];
  const mockStore = configureMockStore(middlewares);

  const store = mockStore();
  return {
    ...render(<Router history={history}><AuthRouter type="private" store={store}>{ui}</AuthRouter></Router>),
    history,
  }
}

afterEach(cleanup)

jest.mock('axios', () => {
  return {
    create: () => {
      return {
        interceptors: {
          request: {eject: jest.fn(), use: jest.fn()},
          response: {eject: jest.fn(), use: jest.fn()},
        },
      };
    },
  };
});

describe('when unauthenticated', () => {

    axios.get.mockImplementation(() => Promise.resolve({ data: {error: 'user or password wrong'} }));
  
    const props = {
      isAuthenticated: false,
    }
  
    it('redirects when authToken invalid', async () => {
      const { history } = renderWithRouter(<Dashboard {...props} />)
      expect(history.location.pathname).toEqual('/')

    })
  })

我得到:TypeError: Cannot read property 'mockImplementation' of undefined

如果我将 axios 的模拟实现更改如下:

jest.mock('axios')

我明白了TypeError: Cannot read property 'interceptors' of undefined

标签: javascriptaxios

解决方案


你试过这样嘲讽吗?

const mockAxios = {
   interceptors: {
      request: {eject: jest.fn(), use: jest.fn()},
      response: {eject: jest.fn(), use: jest.fn()},
   },
};

jest.mock('axios', () => {
  return {
    create: () => {
      return mockAxios;
    },
  };
});

在测试中:

mockAxios.get = jest.fn(() => Promise.resolve({ data: {error: 'user or password wrong'} }));

推荐阅读