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

Next.js测试时router读取失败问题求助

问题:测试React路由跳转按钮时抛出Cannot read properties of null (reading 'push')错误

错误信息

Cannot read properties of null (reading 'push')

      71 |                         className={styles.footerButton}
      72 |                         data-testid="footerButton"
    > 73 |                         onClick={() => router.push('/')}
         |     

测试代码

const buttonElement = screen.getByTestId('footerButton');
expect(buttonElement).toBeInTheDocument();
userEvent.click(buttonElement);

expect(window.location.href).toBe('http://localhost/');

组件代码

<button
  className={styles.footerButtonPC}
  data-testid="footerButtonPC"
  onClick={() => router.push('/')}
>
  Full Fit & Size Guide
</button>

解决方法

  • 修正测试ID不匹配问题:组件里的data-testid是footerButtonPC,但测试代码中用的是footerButton,这会导致无法获取正确的按钮元素,先把这个不一致的问题修复。

  • 模拟路由对象:组件中调用的router通常是通过路由钩子(比如Next.js的useRouter或React Router的useNavigate)获取的,测试环境中没有路由上下文,导致钩子返回null。以Next.js为例,可通过jest模拟路由:

    import { useRouter } from 'next/router';
    jest.mock('next/router', () => ({
      useRouter: () => ({
        push: jest.fn()
      })
    }));
    

    之后在测试中验证push方法是否被正确调用:

    const mockPush = jest.fn();
    jest.mock('next/router', () => ({
      useRouter: () => ({
        push: mockPush
      })
    }));
    
    // 渲染组件、点击按钮后
    userEvent.click(buttonElement);
    expect(mockPush).toHaveBeenCalledWith('/');
    
  • 用路由上下文包裹组件:如果使用React Router,测试时需要用MemoryRouter包裹组件,确保路由上下文存在:

    import { MemoryRouter } from 'react-router-dom';
    
    render(
      <MemoryRouter>
        <YourComponent />
      </MemoryRouter>
    );
    
  • 避免直接断言window.location.href:单页应用的路由跳转通常由路由库内部管理,不会直接修改window.location,应通过模拟路由方法的调用情况来验证跳转逻辑,而不是断言window.location.href。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 08:07:46