Jest mock react-native-keychain时提示getGenericPassword不是函数如何解决
报错由mock文件的导出规则和react-native-keychain@8.x的实际导出规则不匹配导致。
8.x版本的库采用命名导出对外暴露API,没有把所有方法挂在default导出对象上。你当前编写的mock仅提供了default导出,业务代码通过import { getGenericPassword } from 'react-native-keychain'的命名导入语法引入方法时,拿不到对应的mock实现,就会触发“不是函数”的报错。
调整mock文件的位置和内容
如果你之前在__mocks__下创建了react-native-keychain目录,直接删除该目录,在__mocks__根目录新建react-native-keychain.js单文件(Jest对node_modules包的mock,优先识别__mocks__下与包名同名的单js文件,目录形式容易出现解析异常),写入以下代码:const keychainMock = { SECURITY_LEVEL_ANY: 'MOCK_SECURITY_LEVEL_ANY', SECURITY_LEVEL_SECURE_SOFTWARE: 'MOCK_SECURITY_LEVEL_SECURE_SOFTWARE', SECURITY_LEVEL_SECURE_HARDWARE: 'MOCK_SECURITY_LEVEL_SECURE_HARDWARE', setGenericPassword: jest.fn().mockResolvedValue(true), getGenericPassword: jest.fn().mockResolvedValue(false), resetGenericPassword: jest.fn().mockResolvedValue(true), }; // 同时提供default导出和命名导出,完全匹配v8版本的导出规则 export default keychainMock; export const { SECURITY_LEVEL_ANY, SECURITY_LEVEL_SECURE_SOFTWARE, SECURITY_LEVEL_SECURE_HARDWARE, setGenericPassword, getGenericPassword, resetGenericPassword } = keychainMock;显式声明启用mock
node_modules下的第三方包,Jest不会自动读取__mocks__下的mock文件,需要在测试文件顶部,或者Jest配置中setupFilesAfterEnv指定的全局初始化文件里,显式调用mock声明:jest.mock('react-native-keychain');清空Jest缓存后重跑测试
旧的解析缓存会导致mock修改不生效,执行以下命令清空缓存后再跑测试:npx jest --clearCache
如果是TypeScript项目,也可以通过开启编译配置的esModuleInterop: true选项,让Jest自动把default导出的对象映射为命名导入的取值源,但该方案依赖编译配置,兼容性不如直接调整mock导出写法,优先使用上述标准修复步骤。
内容的提问来源于stack exchange,提问作者Florian Weber

