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

在Jest和TypeScript中Mock Axios自定义错误失败的解决方法

在Jest+TypeScript环境中正确Mock Axios的401错误响应

问题背景

测试GetToken函数时,期望捕获带有errors数组的Axios 401错误,提取数组中第一个元素的detail作为错误信息,但实际测试失败:错误信息返回Request failed with status code 400,且代码进入了普通Error的处理分支。

错误原因

  1. Mock未生效:getToken.ts中每次调用都新建了axios实例,而非复用axios-instance.ts导出的实例,导致Jest对axiosInstance的Mock完全没作用。
  2. Mock对象类型错误:直接用普通对象作为拒绝值,不是AxiosError实例,导致e instanceof AxiosError判断不成立,无法进入自定义错误处理分支。

修复步骤

步骤1:修改getToken.ts,复用全局axios实例

把函数内部创建的api替换为导入的axiosInstance,确保请求走Mock的实例:

import axios, { AxiosError } from 'axios';
import { axiosInstance } from '../../utils/axios-instance';
import path from 'path';

// 类型定义(根据实际项目调整)
interface ITokenParams {
  client_id: string;
  client_secret: string;
  code: string;
  grant_type: string;
}

interface ITokenResult { /* 实际返回类型 */ }
interface IApiError { detail: string; }
interface IError { error: boolean; module: string; method: string; message?: string; }

const GetToken = async (params: ITokenParams): Promise<ITokenResult | IError> => {
  try {
    // 替换为复用全局axios实例
    const { data } = await axiosInstance.post<ITokenResult>("https://someURL", { ...params });
    return data;
  } catch (e) {
    let err: IError = {
      error: true,
      module: path.basename(__filename),
      method: GetToken.name
    };
    if (e instanceof AxiosError && e.response?.data?.errors) {
      let errorsArray: IApiError[] = e.response.data.errors;
      err.message = errorsArray.length > 0 ? errorsArray[0].detail : e.message;
    } else if (e instanceof Error) {
      err.message = e.message;
    }
    return err;
  }
};

export default GetToken;

步骤2:修改测试文件,创建正确的AxiosError实例

使用axios.createError方法生成符合要求的AxiosError实例,确保instanceof判断通过:

import { axiosInstance } from '../../utils/axios-instance';
import GetToken from '@App/api/oauth/getToken';
import axios, { AxiosError } from 'axios';

jest.mock('../../utils/axios-instance.ts');

describe('Token from OAuth', () => {
  test('Return error for expired code', async () => {
    // 定义自定义错误响应数据
    const errorResponse = { errors: [{ detail: 'a' }] };
    // 创建AxiosError实例
    const mockError = axios.createError(
      'Unauthorized',
      undefined,
      401,
      {},
      { data: errorResponse }
    );

    const expectedResult = {
      error: true,
      module: 'getToken.ts',
      method: 'GetToken',
      message: 'a'
    };

    // 类型断言为Mock实例
    const mockedAxios = axiosInstance as jest.Mocked<typeof axiosInstance>;
    // Mock post方法的拒绝返回值
    mockedAxios.post.mockRejectedValueOnce(mockError);

    const result = await GetToken({
      client_id: process.env.APPLICATION_ID || '',
      client_secret: process.env.APPLICATION_SECRET || '',
      code: "some-codes",
      grant_type: "authorization_code"
    });

    expect(result).toEqual(expectedResult);
    // 验证post方法的调用参数
    expect(mockedAxios.post).toHaveBeenCalledWith(
      "https://someURL",
      {
        client_id: process.env.APPLICATION_ID || '',
        client_secret: process.env.APPLICATION_SECRET || '',
        code: "some-codes",
        grant_type: "authorization_code"
      }
    );
  });
});

关键说明

  • 复用axios实例:只有请求使用被Mock的实例,Jest的Mock逻辑才会生效;
  • AxiosError实例化:必须用官方提供的createError方法创建错误对象,才能通过instanceof AxiosError的类型校验,进入自定义错误处理分支。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:18:21