【问题标题】:How to mock interceptors when using jest.mock('axios')?使用 jest.mock('axios') 时如何模拟拦截器?
【发布时间】:2020-06-10 03:18:56
【问题描述】:

使用 jest 运行测试时,我有基本的测试套装语法:

jest.mock('axios');

describe('app', () => {
    let render

    beforeEach(() => {
        axiosMock.get.mockResolvedValueOnce({
            data: {greeting: 'hello there'},
        }),
        render= renderApp()
    });

    test('should render something', () => {
        expect(something).toBeInTheDocument();
    });


});

问题是我的代码中有拦截器,当使用 jest 命令输出运行测试时:

TypeError:无法读取未定义的属性“拦截器”

并指向拦截器对象

axiosInstance.interceptors.request.use(...

axiosInstance是存储axios.create返回的变量

export const axiosInstance = axios.create({...

在 SO How do I test axios in jest 上引用了这个 axios 线程,但它不涉及任何拦截器,所以并没有真正的帮助。

【问题讨论】:

    标签: reactjs jestjs axios react-testing-library


    【解决方案1】:

    到此为止,简单明了jest.fn()

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

    【讨论】:

    • 我没有使用 axios.create 创建 axios 实例,如何模拟拦截器?在我的单元测试中,axios 像这样被嘲笑 jest.mock('axios'); const mockedAxios = axios as jest.Mocked;
    【解决方案2】:

    确保模拟出拦截器和axios.create(如果使用):

    // Replace any instances with the mocked instance (a new mock could be used here instead):
    axios.create.mockImplementation((config) => axios);
    
    // Mock out the interceptor (assuming there is only one):
    let requestCallback = () => {
      console.log("There were no interceptors");
    };
    axios.interceptors.request.use.mockImplementation((callback) => {
      requestCallback = callback;
    });
    
    // Mock out the get request so that it returns the mocked data but also calls the 
    // interceptor code:
    axios.get.mockImplementation(() => {
      requestCallback();
      return {
        data: "this is some data"
      };
    });
    

    注意如果这不起作用:

    此示例假定创建和拦截器调用位于 Jest 可以模拟它们的位置。将axios.createaxiosInstance.interceptors.request.use 行放在函数范围之外可能会导致上述模拟失败。这是 Jest 可以模拟出来的示例文件:

    const axios = require('axios');
    
    const DEBUG = true;
    
    const customRequest = (url) => {
      // Example of axios.create from https://www.npmjs.com/package/axios#axioscreateconfig
      const axiosInstance = axios.create({
        baseURL: 'https://some-domain.com/api/',
        timeout: 1000,
        headers: {'X-Custom-Header': 'foobar'}
      });
    
      // Example of interceptor taken from https://stackoverflow.com/a/52737325/7470360:
      axiosInstance.interceptors.request.use((config) => {
        if (DEBUG) { console.info("Request called", config); }
        return config;
      }, (error) => {
        if (DEBUG) { console.error("Request error ", error); }
        return Promise.reject(error);
      });
    
      return axiosInstance.get(url);
    }
    
    module.exports = customRequest;
    

    模拟代码将模拟出axios.create 调用和customRequest 中的axiosInstance 调用。将创建或拦截移到函数外都会导致模拟失败。

    【讨论】:

    • Tnx 的帮助但是我已经能够用通常的 jest.mock('axios',callback) 来模拟它无论如何我遇到了另一个问题,所以如果你可以看看它stackoverflow.com/questions/60428640/…昨天赞成这个答案
    【解决方案3】:

    这是我嘲笑axios.create 及其interceptors 的方式:

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

    之后我可以在我的测试代码中调用以下代码:

    const client = axios.create({
      baseURL: 'http://some-url.com',
    });
    
    client.interceptors.request.use(config => {
      // some other test code
      return config;
    });
    

    【讨论】:

    • 唯一对我有用的例子
    猜你喜欢
    • 2019-06-26
    • 2019-03-15
    • 2020-08-31
    • 2020-09-28
    • 2019-04-28
    • 2021-05-04
    • 1970-01-01
    • 2018-01-20
    • 1970-01-01
    相关资源
    最近更新 更多