Jest测试React Native时mock react-native-firebase报credential读取错误
问题根因
抛出TypeError: Cannot read property 'credential' of undefined的核心原因是mock结构和@react-native-firebase/auth的真实导出结构完全错位:
- 你在
jest.mock('@react-native-firebase/auth', ...)里返回的工厂值是一个独立箭头函数() => mocks.auth,这个函数才是业务代码通过import auth from '@react-native-firebase/auth'拿到的默认导出对象。 - 你把
GoogleAuthProvider静态属性挂在了mocks.auth(一个jest.fn实例)上,根本没挂到那个作为模块导出的箭头函数上。业务代码执行auth.GoogleAuthProvider时,拿到的是没有任何自定义属性的裸箭头函数,访问结果自然是undefined,后续读取.credential就会触发类型错误。 - 存在隐性配置错误:当前GoogleSignin的mock返回的是字符串
'123',但业务代码对signIn的返回值做了{idToken}解构,字符串无法解构出该属性,就算解决了credential的报错,这里也会抛出新的异常。
修正方案
调整两处核心配置:
- 严格对齐auth模块的真实结构:将
GoogleAuthProvider这类静态属性直接挂到auth模块的默认导出(即可调用的mock函数本身)上,不要挂到函数调用后返回的实例对象上。 - 修正GoogleSignin的返回值结构,匹配业务代码的解构逻辑。
修正后的完整测试代码:
import {GoogleLogin} from './GoogleLogin'; // 定义实例方法mock const mockSignInWithCredential = jest.fn(); // 定义credential生成方法mock const mockCredentialFn = jest.fn().mockReturnValue({ providerId: 'google.com', token: 'mock-id-token', secret: 'mock-secret' }); // 定义auth模块的默认导出:本身是可调用函数,同时挂载静态属性 const mockAuth = jest.fn(() => ({ signInWithCredential: mockSignInWithCredential })); // 把GoogleAuthProvider静态属性直接挂到导出的auth函数上,和真实库结构保持一致 mockAuth.GoogleAuthProvider = { credential: mockCredentialFn }; // 配置auth模块的jest mock jest.mock('@react-native-firebase/auth', () => ({ __esModule: true, default: mockAuth })); // 修正GoogleSignin的返回值结构,匹配业务代码的解构逻辑 jest.mock('@react-native-community/google-signin', () => ({ GoogleSignin: { signIn: jest.fn().mockResolvedValue({ idToken: 'mock-google-id-token' }) } })); describe('navigation > auth > GoogleLogin', () => { it('calls signInWithCredential', async () => { await GoogleLogin(); // 验证Google credential生成逻辑触发正确 expect(mockCredentialFn).toHaveBeenCalledWith('mock-google-id-token'); // 验证firebase凭证登录方法触发正确 expect(mockSignInWithCredential).toHaveBeenCalled(); }); });
配置注意事项
- react-native-firebase/auth的真实导出逻辑是:可调用的函数本身携带静态属性(如
GoogleAuthProvider),执行函数后返回带实例方法(如signInWithCredential)的auth实例。编写mock时必须严格对齐这个层级关系,不能混淆静态属性和实例方法的挂载位置。 - 之前的写法错误在于把静态属性挂到了函数返回的实例对象上,而业务代码访问静态属性时根本没有执行函数,自然拿不到对应属性。
- 涉及异步逻辑的mock方法必须返回Promise对象,不能直接返回静态值,否则业务代码执行
await时会拿到undefined,触发解构错误。
内容的提问来源于stack exchange,提问作者Rob Sanins
相关产品推荐
相关产品推荐

