ts-jest中fetchData内部的getToken无法Mock,实际实现仍执行
同文件内函数Mock失效的原因及解决方法
失效核心原因
当fetchData内部直接调用getToken()时,它引用的是模块内部的原始函数,而非模块导出对象上的函数。Jest的Mock机制仅能修改模块导出的对象,但无法改变模块内部的直接函数引用关系——这就是为什么你mock了导出的getToken,但实际运行的还是原始逻辑。
你尝试的方法为什么无效
直接mock导入的
getToken(getToken as jest.Mock).mockResolvedValue(mockedTokenValue);你修改的只是
import进来的getToken引用,而fetchData调用的是模块内部未被修改的原始函数,两者不是同一个引用,所以Mock不生效。部分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
相关产品推荐
相关产品推荐

