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

测试使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:29:57