React Native Jest测试报错:_reactNative.Linking.addEventListener不是函数
问题:React Native Jest测试报错:Linking相关异常
我在全新安装的React Native项目中运行默认Jest测试时遇到异常错误。
测试代码如下:
import 'react-native'; import React from 'react'; import App from '../src/App'; // Note: test renderer must be required after react-native. import renderer from 'react-test-renderer'; it('renders correctly', () => { renderer.create(<App />); });
我的jest.setup.js配置:
// as supplied by the react navigation testing docs import 'react-native-gesture-handler/jestSetup'; // Mock Ionicons pack jest.mock('react-native-vector-icons/Ionicons', () => 'Icon'); // Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
我的babel.config.js配置:
module.exports = { presets: ['module:metro-react-native-babel-preset'], };
运行npm test(即jest命令)后,出现以下错误:
npm test > optionscreener@0.0.1 test > jest ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. at Object.prefixes [as Linking] (node_modules/react-native/index.js:320:12) at subscribe (node_modules/@react-navigation/native/src/useLinking.native.tsx:104:36) at node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js:183:12 at commitHookEffectListMount (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12932:26) at commitPassiveMountOnFiber (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14346:11) at commitPassiveMountEffects_complete (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14306:9) at commitPassiveMountEffects_begin (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14293:7) at commitPassiveMountEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14281:3) at flushPassiveEffectsImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16233:3) at flushPassiveEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16182:14) at node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16002:9 at workLoop (node_modules/scheduler/cjs/scheduler.development.js:266:34) at flushWork (node_modules/scheduler/cjs/scheduler.development.js:239:14) at Immediate.performWorkUntilDeadline [as _onImmediate] (node_modules/scheduler/cjs/scheduler.development.js:533:21) RUNS __tests__/App-test.tsx /Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2608 throw error; ^ TypeError: _reactNative.Linking.addEventListener is not a function at subscribe (/Users/chris/enterprise/OptionScreener/node_modules/@react-navigation/native/src/useLinking.native.tsx:104:45) at /Users/chris/enterprise/OptionScreener/node_modules/@react-navigation/native/lib/commonjs/useLinking.native.js:183:12 at commitHookEffectListMount (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12932:26) at commitPassiveMountOnFiber (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14346:11) at commitPassiveMountEffects_complete (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14306:9) at commitPassiveMountEffects_begin (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14293:7) at commitPassiveMountEffects (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14281:3) at flushPassiveEffectsImpl (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16233:3) at flushPassiveEffects (/Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16182:14) at /Users/chris/enterprise/OptionScreener/node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16002:9 Node.js v18.12.1
我希望Jest和React Native能兼容运行,但目前未能实现,请问问题出在哪里?
解决方案
错误根源是React Navigation的useLinking钩子调用了Linking.addEventListener,但Jest默认的Linking mock没有提供该方法,同时测试中存在异步副作用未被正确处理,导致环境销毁后仍有代码执行。按以下步骤修复:
- 完善Linking模块的Mock
在jest.setup.js中添加完整的Linking mock,覆盖所需方法:
jest.mock('react-native', () => { const originalModule = jest.requireActual('react-native'); return { ...originalModule, Linking: { ...originalModule.Linking, addEventListener: jest.fn(), removeEventListener: jest.fn(), getInitialURL: jest.fn().mockResolvedValue(null), }, }; });
- 异步处理测试中的副作用
将测试改为异步函数,确保所有渲染相关的异步副作用完成后再结束测试:
it('renders correctly', async () => { await renderer.create(<App />); });
- 确认Jest配置的测试环境
在package.json或jest.config.js中检查测试环境设置,确保与React Native兼容:
// package.json中的jest配置示例 "jest": { "preset": "react-native", "setupFilesAfterEnv": ["./jest.setup.js"], "testEnvironment": "jsdom" }
- 临时禁用Linking功能(可选)
如果测试不需要路由跳转逻辑,可在测试时包裹App并禁用Linking:
import { NavigationContainer } from '@react-navigation/native'; it('renders correctly', () => { renderer.create( <NavigationContainer linking={{ enabled: false }}> <App /> </NavigationContainer> ); });
内容的提问来源于stack exchange,提问作者fullStackChris
相关产品推荐
相关产品推荐

