TypeScript+Jest:Mock被测试方法内部readFile返回值失效的解决办法
解决Jest Mock模块内部函数失效的问题
问题核心在于:当loadUsage内部直接调用同模块的readFile时,它用的是函数的本地引用,而非模块导出的引用,导致Jest的mock无法拦截这个调用。以下是两种可行的解决方法:
方法一:修改源文件,通过模块自身引用调用函数
在loadUsage.ts中,让loadUsage通过模块自身的引用来调用readFile,这样就能让Jest的mock生效:
// loadUsage.ts import * as self from './loadUsage'; export async function readFile() { // 真实文件读取逻辑 return 'real data'; } export async function loadUsage() { // 改为通过模块引用调用readFile return await self.readFile(); }
测试文件中使用jest.spyOn替换readFile的实现:
// loadUsage.test.ts import * as loadUsageModule from './loadUsage'; test('loadUsage 应使用 mock 的 readFile', async () => { const mockReadFile = jest.spyOn(loadUsageModule, 'readFile') .mockResolvedValue('mock data'); const result = await loadUsageModule.loadUsage(); expect(result).toBe('mock data'); expect(mockReadFile).toHaveBeenCalledTimes(1); // 测试后恢复原函数 mockReadFile.mockRestore(); });
方法二:不修改源文件,用jest.mock重写模块导出
如果不想改动源文件,可以直接在测试中重写整个模块的导出,保留原模块的其他逻辑,仅替换readFile:
// loadUsage.test.ts // 先mock整个模块 jest.mock('./loadUsage', () => { // 保留原模块的所有导出 const originalModule = jest.requireActual('./loadUsage'); return { ...originalModule, // 替换readFile为mock函数 readFile: jest.fn().mockResolvedValue('mock data') }; }); import { loadUsage, readFile } from './loadUsage'; test('loadUsage 应使用 mock 的 readFile', async () => { const result = await loadUsage(); expect(result).toBe('mock data'); expect(readFile).toHaveBeenCalledTimes(1); });
为什么之前的方法失效?
- 若直接用
jest.mock('./loadUsage')而未保留原模块逻辑,会导致loadUsage也被替换为默认mock函数,不符合需求; - 若源文件中
loadUsage直接调用本地的readFile(而非模块导出的引用),jest.spyOn监听的是导出的函数,自然无法拦截内部的本地调用。
内容的提问来源于stack exchange,提问作者Franva
相关产品推荐
相关产品推荐

