React Native TypeScript测试报RNPermissions null错误如何解决?
问题根因
你当前仅Mock了RN内置的PermissionsAndroid模块,但报错触发自react-native-qrcode-scanner依赖的第三方权限库react-native-permissions,该库未被正确Mock导致加载时检测到Native模块为空。
解决方案
1. 修正权限Mock文件test/mock-permissions.ts
补充对react-native-permissions的Mock逻辑,完整代码如下:
// eslint-disable-next-line react-native/split-platform-components import { PermissionsAndroid } from "react-native"; // 原有内置PermissionsAndroid Mock逻辑 const internetPermissionResult: string = PermissionsAndroid.RESULTS.GRANTED; const vibratePermissionResult: string = PermissionsAndroid.RESULTS.GRANTED; const internetPermissionGranted = true; const vibratePermissionGranted = true; const permissionsAndroidModule = jest.requireActual('react-native/Libraries/PermissionsAndroid/PermissionsAndroid.js'); jest.doMock('react-native/Libraries/PermissionsAndroid/PermissionsAndroid', () => ({ ...permissionsAndroidModule, requestMultiple: () => { return { [PermissionsAndroid.PERMISSIONS.INTERNET]: internetPermissionResult, [PermissionsAndroid.PERMISSIONS.VIBRATE]: vibratePermissionResult, }; }, check: () => { return internetPermissionGranted && vibratePermissionGranted; }, })); // 新增:Mock第三方react-native-permissions库 jest.mock('react-native-permissions', () => ({ PERMISSIONS: { ANDROID: { INTERNET: 'android.permission.INTERNET', VIBRATE: 'android.permission.VIBRATE', }, IOS: {} }, RESULTS: { GRANTED: 'granted', DENIED: 'denied', BLOCKED: 'blocked' }, check: jest.fn(() => Promise.resolve('granted')), request: jest.fn(() => Promise.resolve('granted')), requestMultiple: jest.fn(() => Promise.resolve({ 'android.permission.INTERNET': 'granted', 'android.permission.VIBRATE': 'granted' })) }));
2. 修正AsyncStorage测试逻辑
你当前测试用例中AsyncStorage.getItem的断言存在异步调用未等待的问题,修改login-screen.test.tsx代码如下:
import AsyncStorage from "@react-native-community/async-storage" import { render, waitFor } from "@testing-library/react-native" import React from "react" import { LoginScreen } from ".." // 显式声明AsyncStorage为Mock,避免未Mock的原生模块报错 jest.mock('@react-native-community/async-storage', () => ({ getItem: jest.fn(() => Promise.resolve(null)), setItem: jest.fn(() => Promise.resolve()), removeItem: jest.fn(() => Promise.resolve()), clear: jest.fn(() => Promise.resolve()), })) it("renders correctly", async () => { const { getAllByText } = render(<LoginScreen navigation={undefined} route={undefined} />) expect(getAllByText("Login").length).toBe(1) // 等待异步方法执行完成后再断言 await waitFor(() => { expect(AsyncStorage.getItem).toHaveBeenCalledWith("myKey") }) })
3. 校验Jest配置
确保你的jest.config.js中已经正确配置了setup文件与忽略转译规则,示例配置如下:
module.exports = { preset: 'react-native', setupFilesAfterEnv: [ '<rootDir>/test/setup.ts' ], transformIgnorePatterns: [ 'node_modules/(?!(react-native|@react-native-community|react-native-permissions|react-native-qrcode-scanner)/)' ] }
内容的提问来源于stack exchange,提问作者MIike Eps
相关产品推荐
相关产品推荐

