Jest spyOn无法正常工作问题排查(附示例代码)
问题原因
你的问题核心在于模块内部函数的直接引用导致Jest mock失效:
在app.ts中,main函数直接调用了同文件内定义的method1变量,而非通过模块导出对象(比如app.method1)调用。Jest的spyOn仅能监视模块导出的方法,因此main里的实际调用不会触发你mock的导出版本,进而导致:
- 断言
expect(spy).toHaveBeenCalled()失败(实际调用的是未被mock的本地method1) console.log(cars)输出undefined(原method1未返回有效数据)
解决方案
方案1:修改app.ts,让main通过模块自身调用method1
调整main的调用逻辑,使用模块导出的method1引用:
// app.ts export const method1 = async() => { // some stuff } export const main = async() => { // 使用exports.method1调用 const cars: Car[] = await exports.method1(); console.log(cars); }
也可以通过导入自身模块的方式实现:
// app.ts import * as self from './app'; export const method1 = async() => { // some stuff } export const main = async() => { const cars: Car[] = await self.method1(); console.log(cars); }
方案2:使用Jest模块mock重定向
在测试文件中通过jest.mock重写模块导出,确保main调用的是mock版本:
import * as app from './app'; const cars = []; // some car objects // 保留原模块其他方法,仅mock method1 jest.mock('./app', () => { const originalModule = jest.requireActual('./app'); return { ...originalModule, method1: jest.fn(), }; }); describe('Test', function() { it('test1', async() => { // 给mock的method1设置返回值 (app.method1 as jest.Mock).mockResolvedValue(cars); await app.main(); expect(app.method1).toHaveBeenCalled(); }); });
方案3:拆分模块(推荐)
将method1拆分到独立模块(比如carUtils.ts),让app.ts导入使用,测试时直接mock独立模块的方法:
// carUtils.ts export const method1 = async() => { // some stuff } // app.ts import { method1 } from './carUtils'; export const main = async() => { const cars: Car[] = await method1(); console.log(cars); }
测试文件中直接监视独立模块的方法:
import * as app from './app'; import * as carUtils from './carUtils'; const cars = []; // some car objects describe('Test', function() { it('test1', async() => { const spy = jest.spyOn(carUtils, 'method1'); spy.mockResolvedValue(cars); await app.main(); expect(spy).toHaveBeenCalled(); }); });
内容的提问来源于stack exchange,提问作者Tiago Silva
相关产品推荐
相关产品推荐

