React Native异步组件导致Jest测试失败的解决方法问询
React Native Jest测试报错:ReferenceError: 尝试在Jest环境销毁后导入文件
我给React Native项目的入口组件App.tsx写了基础测试用例,组件接收JSON格式的学生列表props,通过@react-navigation导航到HomeScreen,HomeScreen会调用带异步函数的Students组件。运行npm run test时出现错误:ReferenceError: You are trying to import a file after the Jest environment has been torn down,请问怎么让Jest等待App组件的子组件完成异步操作?
相关代码
App.tsx
import * as React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import HomeScreen from './Screens/HomeScreen'; import { StudentProps, RootStackParamList } from './types/StudentInfo'; export default function App(props: StudentProps): React.JSX.Element { const Stack = createNativeStackNavigator<RootStackParamList>(); return ( <NavigationContainer> <Stack.Navigator initialRouteName="ReactNative"> <Stack.Screen name="ReactNative" component={HomeScreen} initialParams={{ studentList: props }} /> </Stack.Navigator> </NavigationContainer> ); }
App.test.tsx
import 'react-native'; import React from 'react'; import renderer from 'react-test-renderer'; import App from '../App'; test('renders correctly', () => { const tree = renderer .create( <App appList={[ '{"name":"John Doe","course":"Jest"}', '{"name":"Jane Doe","course":"React Native"}' ]} /> ) .toJSON(); expect(tree).toMatchSnapshot(); });
错误信息
> reactnativeproject@0.0.1 test > jest ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From __tests__/App.test.tsx. at Object.get BackHandler [as BackHandler] (node_modules/react-native/index.js:109:12) at node_modules/@react-navigation/native/lib/commonjs/useBackButton.js:50:37 at commitHookEffectListMount (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12999:26) at commitPassiveMountOnFiber (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14422:11) at commitPassiveMountEffects_complete (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14382:9) at commitPassiveMountEffects_begin (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14369:7) at commitPassiveMountEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14357:3) at flushPassiveEffectsImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16248:3) at flushPassiveEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16197:14) at node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16012:9 at workLoop (node_modules/react-test-renderer/node_modules/scheduler/cjs/scheduler.development.js:266:34) at flushWork (node_modules/react-test-renderer/node_modules/scheduler/cjs/scheduler.development.js:239:14) at Immediate.performWorkUntilDeadline [as _onImmediate] (node_modules/react-test-renderer/node_modules/scheduler/cjs/scheduler.development.js:533:21) console.error The above error occurred in the <ForwardRef(NavigationContainerInner)> component: at NavigationContainerInner (C:\Github\bcgov\IAS\ReactNativeProject\node_modules\@react-navigation\native\src\NavigationContainer.tsx:107:23) at App Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. at logCapturedError (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8661:23)
解决方法
这个错误是因为Jest在测试结束后就销毁了运行环境,但子组件的异步操作还在执行,后续触发的代码尝试导入已被销毁环境中的模块导致的。可以通过以下几种方式解决:
1. 改用异步测试,等待渲染完成
React Test Renderer的act()方法可以确保所有状态更新和副作用都处理完毕后再继续测试,把测试改成异步函数即可:
import 'react-native'; import React from 'react'; import renderer from 'react-test-renderer'; import App from '../App'; test('renders correctly', async () => { let tree; await renderer.act(async () => { tree = renderer.create( <App appList={[ '{"name":"John Doe","course":"Jest"}', '{"name":"Jane Doe","course":"React Native"}' ]} /> ); }); expect(tree.toJSON()).toMatchSnapshot(); });
2. Mock导航容器和子组件的异步逻辑
如果测试只是验证App组件的结构和props传递,没必要渲染完整的导航栈和异步组件,直接Mock掉外部依赖更高效:
import 'react-native'; import React from 'react'; import renderer from 'react-test-renderer'; import App from '../App'; import { NavigationContainer } from '@react-navigation/native'; // Mock NavigationContainer,只渲染子元素 jest.mock('@react-navigation/native', () => ({ NavigationContainer: ({ children }) => <div>{children}</div>, })); // Mock HomeScreen,返回占位组件 jest.mock('../Screens/HomeScreen', () => () => <div>HomeScreen</div>); test('renders correctly', () => { const tree = renderer.create( <App appList={[ '{"name":"John Doe","course":"Jest"}', '{"name":"Jane Doe","course":"React Native"}' ]} /> ).toJSON(); expect(tree).toMatchSnapshot(); });
3. 调整Jest配置,延迟环境销毁
如果前两种方法不适用,可以修改Jest配置,延长测试超时时间并延迟环境销毁:
在jest.config.js中添加:
module.exports = { // 保留原有配置,新增以下内容 testTimeout: 10000, // 延长测试超时到10秒 clearMocks: false, // 避免过早清除mock };
同时在jest.setup.js中添加:
jest.useFakeTimers(); jest.runAllTimers();
不过这种是兜底方案,优先推荐前两种方法,尤其是Mock依赖的方式,测试速度更快也更稳定。
内容的提问来源于stack exchange,提问作者JarochoEngineer
相关产品推荐
相关产品推荐

