如何Mock在函数外部实例化的OAuth2客户端?
解决Jest Mock Google OAuth2实例化不生效的问题
问题出在模块加载时机:你的oauth2Client是在generateOAuthLink函数外、模块加载阶段就实例化的,若Jest Mock是在导入被测试模块之后才设置,此时真实的OAuth2已经被用来创建实例,Mock自然不会生效。
解决步骤如下:
1. 在导入被测试模块前完成Mock
必须确保apiCallout.js加载前,就把googleapis模块Mock好,这样模块内的oauth2Client会基于Mock的OAuth2构造函数实例化。
示例测试文件代码:
// 先Mock googleapis,再导入被测试模块 jest.mock('googleapis', () => { // 模拟OAuth2构造函数,返回带有mock方法的实例 const mockOAuth2Instance = { generateAuthUrl: jest.fn(() => 'https://mock-oauth-authorize-url.com') }; const mockOAuth2 = jest.fn(() => mockOAuth2Instance); return { google: { auth: { OAuth2: mockOAuth2 } } }; }); // 现在导入被测试模块,此时模块内的oauth2Client会使用Mock的OAuth2 const { generateOAuthLink } = require('./apiCallout'); describe('generateOAuthLink', () => { it('返回Mock的授权链接', () => { const result = generateOAuthLink(); expect(result).toBe('https://mock-oauth-authorize-url.com'); // 验证OAuth2构造函数是否被正确调用 const { OAuth2 } = require('googleapis').google.auth; expect(OAuth2).toHaveBeenCalled(); // 验证generateAuthUrl方法是否被调用 expect(OAuth2.mock.results[0].value.generateAuthUrl).toHaveBeenCalled(); }); });
2. 按需重置模块缓存(可选)
如果测试需要多次加载apiCallout.js(比如不同测试用例需要不同Mock逻辑),可在每个测试前重置模块缓存,避免之前的实例残留:
beforeEach(() => { jest.resetModules(); }); test('使用不同Mock的场景', () => { // 临时Mock googleapis jest.mock('googleapis', () => { const mockOAuth2 = jest.fn(() => ({ generateAuthUrl: jest.fn(() => 'https://another-mock-url.com') })); return { google: { auth: { OAuth2: mockOAuth2 } } }; }); const { generateOAuthLink } = require('./apiCallout'); expect(generateOAuthLink()).toBe('https://another-mock-url.com'); });
核心逻辑就是让Mock优先于被测试模块加载,确保模块初始化时使用的是Mock构造函数,而非真实的Google API实现。
内容的提问来源于stack exchange,提问作者hungry-hippo56
相关产品推荐
相关产品推荐

