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

React Native单元测试疑问:为何需Mock依赖及Messaging报错解决

React Native测试:Mock依赖必要性与Messaging报错解决

一、为何简单测试也需要Mock Redux、AsyncStorage、Messaging等依赖?

  • 单元测试的隔离性要求:单元测试核心是验证组件自身逻辑,必须排除外部依赖干扰。比如AsyncStorage是原生模块,测试环境无原生运行时支持,直接调用会报错;Redux、Messaging属于外部服务/库,不Mock会让测试耦合第三方逻辑,无法精准验证组件渲染逻辑。
  • 避免副作用:第三方库的真实调用可能产生副作用(如网络请求、本地存储读写),Mock能消除这些副作用,让测试更快、更稳定,结果更可控。
  • 填补测试环境缺失的上下文:像React Navigation的useNavigation、Firebase Messaging的messaging()这类工具,依赖特定运行时上下文,测试环境中没有这些上下文,必须通过Mock提供模拟实现才能避免报错。

二、TypeError: (0 , _messaging.default) is not a function 报错解决

问题原因

你的Messaging Mock结构不符合@react-native-firebase/messaging的导出方式,且缺少代码中用到的getInitialNotification方法。从报错看,组件中调用的是messaging()默认导出函数,但你的Mock写法没有正确模拟这个函数结构。

解决方案

修改Messaging的Mock代码,直接返回模拟函数,并补充getInitialNotification方法:

jest.mock('@react-native-firebase/messaging', () => jest.fn(() => ({
  getToken: jest.fn(() => Promise.resolve('mocked-token')),
  onMessage: jest.fn(),
  onNotificationOpenedApp: jest.fn(),
  onNotification: jest.fn(),
  getInitialNotification: jest.fn(() => Promise.resolve(null)), // 新增组件中用到的方法
})));

如果组件中是命名导入(即import { messaging } from '@react-native-firebase/messaging'),则调整Mock为:

jest.mock('@react-native-firebase/messaging', () => ({
  messaging: jest.fn(() => ({
    getToken: jest.fn(() => Promise.resolve('mocked-token')),
    onMessage: jest.fn(),
    onNotificationOpenedApp: jest.fn(),
    onNotification: jest.fn(),
    getInitialNotification: jest.fn(() => Promise.resolve(null)),
  })),
}));

额外注意

如果LoginScreen依赖Redux,还需要补充Redux钩子的Mock:

jest.mock('react-redux', () => ({
  useSelector: jest.fn().mockReturnValue({}),
  useDispatch: jest.fn().mockReturnValue(jest.fn()),
}));

完整Mock示例(修改后)

/* eslint-disable no-undef */
import '@testing-library/jest-native/extend-expect';

jest.mock('@react-native-async-storage/async-storage', () =>
  require('@react-native-async-storage/async-storage/jest/async-storage-mock'),
);

jest.mock('@react-navigation/native', () => ({
  useNavigation: jest.fn(),
  useRoute: jest.fn(),
  useIsFocused: jest.fn(),
  useFocusEffect: jest.fn().mockImplementation(callback => callback()),
}));

// 修改后的Messaging Mock
jest.mock('@react-native-firebase/messaging', () => jest.fn(() => ({
  getToken: jest.fn(() => Promise.resolve('mocked-token')),
  onMessage: jest.fn(),
  onNotificationOpenedApp: jest.fn(),
  onNotification: jest.fn(),
  getInitialNotification: jest.fn(() => Promise.resolve(null)),
})));

jest.mock('react-native-device-info', () => ({
  getDeviceName: jest.fn(() => Promise.resolve('mocked-device-name')),
  getDeviceId: jest.fn(() => Promise.resolve('mocked-device-id')),
}));

// 新增Redux Mock(如果组件依赖)
jest.mock('react-redux', () => ({
  useSelector: jest.fn().mockReturnValue({}),
  useDispatch: jest.fn().mockReturnValue(jest.fn()),
}));

内容的提问来源于stack exchange,提问作者mehmettalhairmak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 01:11:27