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

React Native自定义Native Module引发单元测试报错如何解决

问题根因

TypeScript类型声明文件仅作用于编译阶段的类型校验,不会改变运行时代码逻辑。单元测试运行在Node/jsdom环境,不会加载Android/iOS端的原生代码,因此NativeModules.SomeModule在测试环境下默认值为undefined,访问其HelloWorld属性时就会抛出TypeError: Cannot read property 'HelloWorld' of undefined错误,和类型声明是否编写无关。

解决方案

方案1:测试框架层Mock原生模块(推荐)

以最常用的Jest测试框架为例,通过Mock注入原生模块的模拟实现,让测试环境下可以正常访问模块方法,有两种常见实现:

  • 全局Mock:在项目根目录或测试目录下创建__mocks__/react-native.js文件,全局替换react-native导出的NativeModules对象
const actualReactNative = jest.requireActual('react-native');
actualReactNative.NativeModules.SomeModule = {
  HelloWorld: jest.fn((addedText) => {
    // 可根据测试需求自定义模拟返回值
    return addedText;
  })
};
export default actualReactNative;
  • 单用例Mock:在具体测试文件的钩子函数中临时注入Mock,避免全局污染
import { NativeModules } from 'react-native';
import { helloWorld } from './path-to-your-native-module-file';

describe('Native module method test', () => {
  const mockHelloWorld = jest.fn();
  beforeEach(() => {
    // 每个用例执行前重置Mock实现
    mockHelloWorld.mockReset();
    NativeModules.SomeModule = {
      HelloWorld: mockHelloWorld
    };
  });

  it('should invoke HelloWorld with passed parameter', () => {
    const testParam = 'test content';
    helloWorld(testParam);
    expect(mockHelloWorld).toHaveBeenCalledWith(testParam);
  });
});

方案2:业务代码层增加空值兜底

在JS侧引用原生模块时增加空值判断,给非原生环境(测试、Web端等)提供兜底实现,从根源避免undefined访问错误:

import { NativeModules } from 'react-native';

// 原生模块不存在时使用兜底实现
const Thing = NativeModules.SomeModule ?? {
  HelloWorld: (addedText: string) => {
    // 非原生环境自定义逻辑,比如打印日志、返回模拟值
    console.log('non-native env HelloWorld called:', addedText);
    return addedText;
  }
};

export const helloWorld = (addedText: string) => {
  return Thing.HelloWorld(addedText);
};

export default Thing;
补充说明

你之前编写的d.ts类型声明写法存在错误,正确的类型声明需要扩展React Native的NativeModules类型定义,参考写法如下:

// someModule.d.ts
import 'react-native';
declare module 'react-native' {
  interface NativeModulesStatic {
    SomeModule: {
      HelloWorld: (addedText: string) => void;
    }
  }
}

注意:类型声明仅用于TS编译时的类型校验和提示,不会生成任何运行时代码,因此仅补充d.ts文件无法解决单元测试的运行时报错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:27:39