You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 19:24:02