测试使用expo-router useRouter的React-Native组件时导航对象缺失报错
解决Expo Router中useRouter组件测试的导航对象缺失问题
问题背景
测试使用expo-router的useRouter的React Native组件时,报错Couldn't find a navigation object. Is your component inside NavigationContainer?,但Expo Router并不使用NavigationContainer,且尝试mockuseRouter后仍未解决。
核心原因
useRouter依赖Expo Router内部的导航上下文,测试环境中未加载该上下文,之前的mock方式未正确返回符合要求的路由对象,导致报错。
解决方案
1. 正确全局mock useRouter
在测试文件顶部添加jest.mock,模拟expo-router的useRouter函数,返回包含组件所需路由方法的对象(组件用到replace,按需添加其他方法):
import { useRouter } from 'expo-router'; // 全局mock useRouter,返回带模拟方法的路由对象 jest.mock('expo-router', () => ({ useRouter: jest.fn(() => ({ replace: jest.fn(), // 若组件用到push、back等其他路由方法,需在此添加对应模拟 })), }));
2. 调整测试代码(结合你的renderWithProvider)
修改测试案例,使用renderWithProvider包裹组件,还可按需验证路由方法的调用逻辑:
import { screen } from '@testing-library/react-native'; import CustomComponent from '../CustomComponent'; import { renderWithProvider } from '../path-to-renderWithProvider'; import { useRouter } from 'expo-router'; import PATHS from '../path-to-paths'; describe('CustomComponent', () => { it('渲染正常并显示标题', () => { renderWithProvider(<CustomComponent />); expect(screen.getByText('title')).toBeOnTheScreen(); }); it('点击时调用router.replace', () => { // 自定义mock的replace方法,用于验证调用 const mockReplace = jest.fn(); (useRouter as jest.Mock).mockReturnValue({ replace: mockReplace }); renderWithProvider(<CustomComponent />); // 触发HCard的点击事件 screen.getByText('title').props.pressAction(); // 验证replace是否被正确调用 expect(mockReplace).toHaveBeenCalledWith(PATHS.DASHBOARD); }); });
关键说明
- 确保mock的
useRouter返回对象包含组件实际使用的所有路由方法,否则仍可能出现上下文缺失错误。 jest.mock需放在测试文件最外层,确保组件导入前完成mock,避免加载真实的useRouter。
内容的提问来源于stack exchange,提问作者Coman Vladut
相关产品推荐
相关产品推荐

