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

ts-jest中fetchData内部的getToken无法Mock,实际实现仍执行

同文件内函数Mock失效的原因及解决方法

失效核心原因

当fetchData内部直接调用getToken()时,它引用的是模块内部的原始函数,而非模块导出对象上的函数。Jest的Mock机制仅能修改模块导出的对象,但无法改变模块内部的直接函数引用关系——这就是为什么你mock了导出的getToken,但实际运行的还是原始逻辑。

你尝试的方法为什么无效

  1. 直接mock导入的getToken

    (getToken as jest.Mock).mockResolvedValue(mockedTokenValue);
    

    你修改的只是import进来的getToken引用,而fetchData调用的是模块内部未被修改的原始函数,两者不是同一个引用,所以Mock不生效。

  2. 部分Mock模块导出

    jest.mock("./handler", () => ({
      ...jest.requireActual("./handler"),
      getToken: jest.fn().mockImplementation(() => "mocked_token")
    }));
    

    这种方式确实替换了模块导出的getToken,但fetchData内部依然直接调用原始的getToken,没有使用导出的Mock版本,所以真实逻辑还是会执行。

无需移文件的解决方法

方法一:修改内部调用为通过模块导出对象调用

调整handler.ts里的fetchData,让它通过模块自身的导出对象调用getToken:

// handler.ts
import * as self from './handler';

export const fetchData = async (params: {}): Promise<any> => {
  try {
    console.log("called fetchData");
    const tokenValue = await self.getToken(params); // 改为通过导出对象调用
    const response = await axios.post(`url`, params, {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + tokenValue,
      },
    });
    return response.data.body;
  } catch (e) {
    throw new Error("Exception caught");
  }
};

方法二:使用jest.spyOn结合模块导出对象

测试文件中通过监听模块导出的getToken来替换为Mock函数:

// handler.test.ts
import * as handler from './handler';
import axios from 'axios';

test('fetchData uses mocked getToken', async () => {
  const mockedTokenValue = 'mocked_token';
  const mockResponse = { data: { body: 'test_result' } };

  // 监听并Mock getToken
  const getTokenSpy = jest.spyOn(handler, 'getToken').mockResolvedValue(mockedTokenValue);
  // Mock axios.post
  jest.spyOn(axios, 'post').mockResolvedValue(mockResponse);

  const result = await handler.fetchData({});

  expect(getTokenSpy).toHaveBeenCalled();
  expect(result).toBe('test_result');

  // 清理Mock
  getTokenSpy.mockRestore();
  jest.restoreAllMocks();
});

方法三:重构为类/对象方法(可选)

把函数封装到对象或类中,通过实例调用,Mock会更直观:

// handler.ts
export const ApiClient = {
  async getToken(params: {}): Promise<string> {
    // 原getToken逻辑
  },
  async fetchData(params: {}): Promise<any> {
    const token = await this.getToken(params);
    // 原fetchData逻辑
  }
};

测试时直接MockApiClient.getToken即可。

内容的提问来源于stack exchange,提问作者Martín Cortés

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:06:04