如何用Jest模拟JavaScript类所有方法并避免调用报错?
Jest 模拟 AppInsightsService 类的正确方式
针对你遇到的 appInsightsService.postEvent is not a function 报错,本质是mock的实例没有提供工具类需要调用的方法。以下是几种可靠的实现方式:
方法1:手动模拟模块导出的类
如果 AppInsightsService 是作为命名导出的类(比如在 app-insights-service.js 中),可以直接用 jest.mock 生成带所有必要方法的mock实例:
// 导入目标模块和工具类 import { AppInsightsService } from './app-insights-service'; import OrderHistoryTool from './order-history-tool'; // mock 整个类,让实例拥有所有需要的空方法 jest.mock('./app-insights-service', () => ({ AppInsightsService: jest.fn().mockImplementation(() => ({ postEvent: jest.fn(), trackMetric: jest.fn(), logError: jest.fn() // 工具类调用到的其他方法都在这里声明为 jest.fn() })) })); test('OrderHistoryTool 能正常使用 mock 的服务实例', () => { const mockService = new AppInsightsService(); const tool = new OrderHistoryTool(mockService); // 执行工具类中会调用 postEvent 的方法 tool.triggerEvent(); // 可选:验证方法是否被调用 expect(mockService.postEvent).toHaveBeenCalled(); });
方法2:动态生成所有方法(无需提前列举)
如果不想手动列出所有方法,可以用 Proxy 动态生成mock方法,任何被调用的方法都会自动变成 jest.fn():
import OrderHistoryTool from './order-history-tool'; test('用 Proxy 动态创建 mock 实例', () => { // 创建一个代理对象,访问任何属性都会返回 jest.fn() const mockService = new Proxy({}, { get(target, prop) { target[prop] = target[prop] || jest.fn(); return target[prop]; } }); const tool = new OrderHistoryTool(mockService); tool.triggerEvent(); expect(mockService.postEvent).toHaveBeenCalled(); });
方法3:处理默认导出的类
如果 AppInsightsService 是默认导出的类,调整mock结构即可:
import AppInsightsService from './app-insights-service'; import OrderHistoryTool from './order-history-tool'; jest.mock('./app-insights-service', () => ({ default: jest.fn().mockImplementation(() => ({ postEvent: jest.fn(), // 其他方法... })) })); // 后续测试逻辑和方法1一致
报错原因说明
之前的mock方式大概率只mock了类的构造函数,但没有给实例挂载对应的方法,导致工具类调用 postEvent 时找不到该函数。上面的方法都确保了mock实例拥有工具类需要的所有可调用方法,既不会报错,也能支持调用验证(如果需要)。
内容的提问来源于stack exchange,提问作者Westy
相关产品推荐
相关产品推荐

