You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试带有Interceptor的Axios服务?Jest测试拦截器难题

问题描述

我有一个全局使用的Axios拦截器实例,代码如下:

export const http = axios.create({
  baseURL: process.env.REACT_APP_API_BASE_URL,
  headers: {
    "CONTENT-TYPE": "application/json",
    ACCEPT: "application/json",
  },
});

/**
 * Add access token in the authorization header of the given config.
 *
 * @param {Object} axiosConfig Axios config object.
 * @param {String} accessToken
 * @returns {Object} Axios config object.
 */
const configWithAccessToken = (
  axiosConfig: AxiosRequestConfig,
  accessToken: string | null
): AxiosRequestConfig => ({
  ...axiosConfig,
  headers: {
    ...axiosConfig.headers,
    Authorization: `Bearer ${accessToken}`,
  },
});

/**
 * Request interceptors for axios instance.
 *
 * @returns {Object}
 */
http.interceptors.request.use(
  (requestConfig: AxiosRequestConfig): AxiosRequestConfig | any => {
    const accessToken = getAccessToken();

    return configWithAccessToken(requestConfig, accessToken);
  },
  (requestError) => {
    throw requestError;
  }
);

/**
 * Response interceptor for axios instance.
 *
 * @returns {Object}
 */
http.interceptors.response.use(
  (response) => {
    return response?.data;
  },
  (error) => {
    if (isEmpty(error)) {
      throw new Error(error);
    }

    const { data } = error?.response;

    throw data;
  }
);

我要测试的服务函数是:

export const fetchAll = () => {
  const url = 'somethingurl/students';

  return http.get(url);
};

测试时拦截器总会被触发,试过Jest Mock但没用,请问怎么绕过拦截器或者正确Mock这个服务?


解决方案

方法1:直接Mock自定义的Axios实例(推荐)

不需要处理拦截器,直接Mock你导出的http实例的get方法,请求根本不会走到拦截器逻辑里。

测试文件代码示例:

import { http } from './path-to-your-axios-instance';
import { fetchAll } from './path-to-your-service';

// Mock http.get 方法
jest.mock('./path-to-your-axios-instance', () => ({
  http: {
    get: jest.fn()
  }
}));

describe('fetchAll', () => {
  it('should call http.get with correct URL', async () => {
    // 模拟成功返回的数据
    const mockData = [{ id: 1, name: 'Student A' }];
    (http.get as jest.Mock).mockResolvedValue(mockData);

    const result = await fetchAll();

    expect(http.get).toHaveBeenCalledWith('somethingurl/students');
    expect(result).toEqual(mockData);
  });

  it('should handle error correctly', async () => {
    // 模拟错误返回
    const mockError = { message: 'Failed to fetch' };
    (http.get as jest.Mock).mockRejectedValue(mockError);

    await expect(fetchAll()).rejects.toEqual(mockError);
  });
});

方法2:清除Axios实例的拦截器

如果需要真实调用Axios但跳过拦截器,可以在测试前清除实例的请求和响应拦截器:

import { http } from './path-to-your-axios-instance';
import { fetchAll } from './path-to-your-service';
import MockAdapter from 'axios-mock-adapter';

describe('fetchAll', () => {
  beforeEach(() => {
    // 清除所有请求拦截器
    http.interceptors.request.clear();
    // 清除所有响应拦截器
    http.interceptors.response.clear();
  });

  it('should make a GET request to correct URL', async () => {
    // 用axios-mock-adapter Mock请求
    const mockAdapter = new MockAdapter(http);
    mockAdapter.onGet('somethingurl/students').reply(200, [{ id: 1 }]);

    const result = await fetchAll();
    expect(result).toEqual([{ id: 1 }]);
  });
});

注意:需要先安装依赖包:npm install axios-mock-adapter --save-dev

方法3:Mock拦截器依赖的函数

如果拦截器里用到了getAccessToken这类外部函数,可以Mock这个函数来避免拦截器抛出问题:

import { getAccessToken } from './path-to-your-auth-utils';
import { fetchAll } from './path-to-your-service';
import { http } from './path-to-your-axios-instance';
import MockAdapter from 'axios-mock-adapter';

jest.mock('./path-to-your-auth-utils', () => ({
  getAccessToken: jest.fn().mockReturnValue('mock-token')
}));

describe('fetchAll', () => {
  it('should include token in headers', async () => {
    const mockAdapter = new MockAdapter(http);
    mockAdapter.onGet('somethingurl/students').reply((config) => {
      expect(config.headers.Authorization).toBe('Bearer mock-token');
      return [200, []];
    });

    await fetchAll();
  });
});

内容的提问来源于stack exchange,提问作者Biswas Rai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 12:05:29