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

在setupTests中初始化Backend类时,Jest模拟axios失效问题

问题原因与解决方案

核心问题:模块缓存导致Backend引用未Mock的axios

当你在setupTests.js中提前创建Backend实例时,Node.js的模块缓存机制会保留Backend首次加载时引用的原始axios实例。后续测试文件中通过jest.mock("axios")生成的Mock axios,无法替换Backend内部已经绑定的原始axios。这就导致测试中调用getList时,实际执行的是原始axios的get方法,而非你设置的Mock函数,最终触发stub未被调用的断言失败。


解决方案

方案1:在setupTests中提前Mock axios

确保setupTests.js在创建Backend实例前就Mock axios,让Backend从一开始就引用Mock版本的axios:

import "@testing-library/jest-dom";
import axios from "axios";
import {Backend} from "./shared/utils/backend";

// 提前Mock axios,覆盖全局模块
jest.mock("axios");
// 可按需给get方法设置默认Mock实现
jest.spyOn(axios, 'get').mockResolvedValue({ data: [] });

new Backend("test");

方案2:给Backend添加axios依赖注入(推荐)

修改Backend类,允许在构造函数中传入自定义axios实例,彻底解耦模块依赖,从根源避免缓存问题:

import axios from "axios";

export class Backend {
  private _baseUrl: string;
  private _axios;

  // 新增可选参数,默认使用全局axios
  constructor(baseUrl: string, axiosInstance = axios) {
    this._axios = axiosInstance;
    this._axios.defaults.headers.get["Access-Control-Allow-Origin"] = "*";
    this._axios.defaults.headers.get["Access-Control-Allow-Credentials"] = "true";
    this._baseUrl = baseUrl;
  }

  async getList(url: string): Promise<any[] | undefined> {
    // 使用实例化的_axios而非全局axios
    const data = await this._axios.get<any[]>(`${this._baseUrl}/${url}`);
    return data?.data;
  }
}

测试文件中直接传入Mock的axios:

import {Backend} from "../../../shared/utils/backend";
import axios from "axios";

jest.mock("axios");

describe("backend", () => {
   test("When getList is called data is returned", async () => {
    const mockGet = jest.fn().mockResolvedValue({
      data: [{ prop: "test", otherProp: 2 }]
    });
    (axios.get as jest.Mock) = mockGet;

    // 传入Mock的axios实例
    const backend = new Backend("baseUrl", axios);
    const data = await backend.getList("testUrl");
    
    expect(mockGet).toHaveBeenCalledWith("baseUrl/testUrl");
    expect(data).toHaveLength(1);
  });
});

setupTests中创建实例时也可传入Mock axios:

import "@testing-library/jest-dom";
import axios from "axios";
import {Backend} from "./shared/utils/backend";

jest.mock("axios");
new Backend("test", axios);

方案3:测试前清除模块缓存

通过jest.resetModules()清除模块缓存,让测试文件重新加载Backend和axios,确保Backend引用Mock的axios:

describe("backend", () => {
  beforeEach(() => {
    // 每次测试前重置模块缓存
    jest.resetModules();
  });

  test("When getList is called data is returned", async () => {
    // 重新Mock axios并导入Backend
    jest.mock("axios");
    const axios = require("axios").default;
    const { Backend } = require("../../../shared/utils/backend");

    const mockGet = jest.fn().mockResolvedValue({
      data: [{ prop: "test", otherProp: 2 }]
    });
    (axios.get as jest.Mock) = mockGet;

    const backend = new Backend("baseUrl");
    const data = await backend.getList("testUrl");
    
    expect(mockGet).toHaveBeenCalledWith("baseUrl/testUrl");
    expect(data).toHaveLength(1);
  });
});

此方案需手动重新导入模块,操作繁琐,仅作为临时替代方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 17:09:24