使用Jest模拟第三方库仍调用真实内部实现的问题排查
问题原因及解决方案
问题原因
- Jest Mock 时机错误:
jest.mock被放在beforeEach函数内,而 Jest 的模块 mocking 机制是在模块加载阶段生效的。业务代码在测试代码执行前就已经导入了真实的ChatSession,导致后续的 mock 无法覆盖真实实现。 - Mock 方式错误:你模拟的
ChatSession是一个普通对象,而非可实例化的类(构造函数)。当执行new ChatSession('', '')时,实际调用的仍是原库中的真实构造函数,最终触发了真实的sendMessage方法,进而调用fetch导致报错。
解决方案
方案一:顶层配置正确的类 Mock
将 jest.mock 移到测试文件的最顶层,并正确模拟 ChatSession 构造函数及其方法:
// 放在测试文件最顶部,模块导入之前 jest.mock('@google/generative-ai', () => ({ // 模拟构造函数,返回带有sendMessage方法的实例 ChatSession: jest.fn().mockImplementation(() => ({ sendMessage: jest.fn().mockResolvedValue({ response: { text: jest.fn().mockResolvedValue('模拟返回内容') } }) })) })); import sendMessage from '../../src/logic/actions/sendMessage'; import { ChatSession } from '@google/generative-ai'; let defaultParams: SendMessageParams; beforeEach(() => { // 重置mock (ChatSession as jest.Mock).mockClear(); const mockChatSession = new ChatSession('', '') as jest.Mocked<ChatSession>; defaultParams = { chatSession: mockChatSession, // ... 其他参数 }; }); afterEach(() => { jest.clearAllMocks(); }); it('should send message', async () => { await sendMessage(defaultParams); // 验证sendMessage被调用 expect(defaultParams.chatSession?.sendMessage).toHaveBeenCalled(); });
方案二:手动传入 Mock 实例(无需模块级 Mock)
直接创建一个符合 ChatSession 类型的 mock 对象,传入测试参数,避免依赖模块 mocking:
import sendMessage from '../../src/logic/actions/sendMessage'; import type { ChatSession } from '@google/generative-ai'; let defaultParams: SendMessageParams; beforeEach(() => { // 手动创建mock实例 const mockChatSession = { sendMessage: jest.fn().mockResolvedValue({ response: { text: jest.fn().mockResolvedValue('模拟返回内容') } }) } as unknown as ChatSession; defaultParams = { chatSession: mockChatSession, // ... 其他参数 }; }); afterEach(() => { jest.clearAllMocks(); }); it('should send message', async () => { await sendMessage(defaultParams); expect(defaultParams.chatSession.sendMessage).toHaveBeenCalled(); });
补充:若需解决 fetch 问题(非必要,仅当未完全 mock 时)
如果因某些原因仍触发真实请求,可在 Jest 配置中启用 fetch:
- 在
jest.config.js中设置testEnvironment: 'node'(Node 20+ 原生支持 fetch) - 或者安装
whatwg-fetch,并在测试入口导入:import 'whatwg-fetch';
内容的提问来源于stack exchange,提问作者Eray Erdin
相关产品推荐
相关产品推荐

