Jest测试时TurboModuleRegistry.getEnforcing找不到NativeAppInfo模块的报错求助
Jest测试时TurboModuleRegistry.getEnforcing找不到NativeAppInfo模块的报错求助
问题描述
我的React Native项目在Android真机和模拟器上运行完全正常,页面中调用NativeAppInfo这个TurboModule也没有问题,但Jest测试一直失败。
我的NativeAppInfo模块代码
import type { TurboModule } from "react-native"; import { TurboModuleRegistry } from "react-native"; export interface Spec extends TurboModule { getAppVersion(): string; } export default TurboModuleRegistry.getEnforcing<Spec>("NativeAppInfo");
Jest报错信息
FAIL __tests__/App.test.tsx ● Test suite failed to run Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'NativeAppInfo' could not be found. Verify that a module by this name is registered in the native binary. 6 | } 7 | > 8 | export default TurboModuleRegistry.getEnforcing<Spec>("NativeAppInfo"); | ^ 9 | at invariant (node_modules/invariant/invariant.js:40:15) at Object.getEnforcing (node_modules/react-native/Libraries/TurboModule/TurboModuleRegistry.js:47:12) at Object.getEnforcing (specs/NativeAppInfo.ts:8:36) at Object.require (src/pages/settings/index.tsx:11:1) at Object.require (src/router/StackProfileNavigator.tsx:9:1) at Object.require (src/router/BottomTabMenuNavigator.tsx:14:1) at Object.require (src/router/StackRootNavigator.tsx:8:1) at Object.require (src/router/index.tsx:1:1) at Object.require (App.tsx:6:1) at Object.require (__tests__/App.test.tsx:5:1) Test Suites: 1 failed, 3 passed, 4 total Tests: 4 passed, 4 total Snapshots: 2 passed, 2 total Time: 2.057 s, estimated 8 s Ran all test suites.
我的Jest配置
/** * @type {import("jest").Config} */ module.exports = { preset: "react-native", transformIgnorePatterns: [ "node_modules/(?!(@react-native|react-native|@react-navigation)/)", ], moduleNameMapper: { "\\.(ttf)$": "<rootDir>/__mocks__/file-mock.js", }, setupFiles: ["<rootDir>/__mocks__/jestSetupFiles/setup.js"], };
我试过很多方法都没解决,有没有大佬能救救我?
解决方案
别慌,这个问题我之前也碰到过!你的项目在Android上能正常运行,是因为原生端已经注册了NativeAppInfo这个TurboModule,但Jest是纯JavaScript的测试环境,根本没法加载原生代码,所以才会抛出这个找不到模块的错误。咱们只需要给这个TurboModule写个Mock就能解决,下面给你几个实用的方案:
方案一:全局Mock(推荐,一次配置所有测试生效)
你已经在jest.config里配置了setupFiles指向__mocks__/jestSetupFiles/setup.js,直接在这个setup文件里添加Mock代码就行:
import { TurboModuleRegistry } from 'react-native'; // Mock TurboModuleRegistry,针对NativeAppInfo返回模拟实现 jest.mock('react-native/Libraries/TurboModule/TurboModuleRegistry', () => { const originalModule = jest.requireActual('react-native/Libraries/TurboModule/TurboModuleRegistry'); return { ...originalModule, getEnforcing: jest.fn((moduleName) => { // 只针对我们的NativeAppInfo做Mock,其他模块保持原逻辑 if (moduleName === 'NativeAppInfo') { return { getAppVersion: jest.fn(() => '1.0.0'), // 这里可以自定义模拟返回的版本号 }; } return originalModule.getEnforcing(moduleName); }), }; });
保存后重新跑测试,应该就能绕过这个错误了。
方案二:在模块文件里做环境判断导出
如果你不想全局Mock,也可以直接在NativeAppInfo.ts里根据环境做条件导出:
import type { TurboModule } from "react-native"; import { TurboModuleRegistry } from "react-native"; export interface Spec extends TurboModule { getAppVersion(): string; } let NativeAppInfo: Spec; // 测试环境下用模拟实现,生产/开发环境用真实的TurboModule if (process.env.NODE_ENV === 'test') { NativeAppInfo = { getAppVersion: () => '1.0.0', } as Spec; } else { NativeAppInfo = TurboModuleRegistry.getEnforcing<Spec>("NativeAppInfo"); } export default NativeAppInfo;
这种方式更贴近模块本身的逻辑,也不用改动Jest的全局配置。
方案三:在单个测试文件里局部Mock
如果只是某个测试文件需要用到这个模块,也可以在测试文件顶部直接Mock:
// 在__tests__/App.test.tsx顶部添加 jest.mock('../specs/NativeAppInfo', () => ({ default: { getAppVersion: jest.fn(() => '1.0.0'), }, }));
这种方式适合只需要在特定测试中覆盖的场景。
补充说明
你可以根据自己的测试需求调整Mock函数的返回值,比如getAppVersion可以返回不同的版本号,用来测试不同的业务逻辑。
内容来源于stack exchange
相关产品推荐
相关产品推荐

