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

Next.js LeftSidebar组件测试:router.push模拟调用失败排查

问题排查与修复

核心问题分析

  1. 路由模块混淆:组件使用的是Next.js App Router的next/navigation模块的useRouter,但测试中同时mock了旧版Pages Router的next/router模块,且在beforeEach中错误操作了next/router的useRouter,完全没有作用到组件实际依赖的路由方法。
  2. 拼写错误:beforeEach里的ussRouter()是useRouter()的拼写错误,直接导致打印的router为undefined。
  3. Mock未正确关联:初始mocknext/navigation的useRouter时返回了自带的push jest函数,但后续没有将这个函数与测试中的mockPush关联,导致断言时mockPush未被调用。

修复步骤

  1. 移除无用的next/router mock:组件未使用该模块,直接删除相关导入和mock代码。
  2. 修正拼写错误:将ussRouter()改为useRouter()。
  3. 正确覆盖next/navigation的useRouter mock:在beforeEach中直接mocknext/navigation的useRouter,让它返回包含自定义mockPush的对象,确保组件调用的router.push就是我们的mock函数。
  4. 统一usePathname的mock:根据测试场景,可按需设置usePathname的返回值,确保组件的激活状态逻辑正常。

修复后的测试代码

import { fireEvent, render, screen } from '@testing-library/react';
import React from 'react';
import { useRouter, usePathname } from 'next/navigation';

import { LeftSideBar } from './LeftSidebar';
import { leftSidebarItems } from './LeftSidebarItems';

// 只mock组件实际使用的next/navigation模块
jest.mock('next/navigation', () => ({
  useRouter: jest.fn(),
  usePathname: jest.fn(),
}));

describe('LeftSideBar', () => {
  describe('Click event on Sidebar', () => {
    let mockPush: jest.Mock;

    beforeEach(() => {
      // 初始化mockPush
      mockPush = jest.fn();
      // 覆盖useRouter的mock,返回包含mockPush的router对象
      (useRouter as jest.Mock).mockReturnValue({
        push: mockPush,
      });
      // 按需设置usePathname的返回值,这里默认返回根路径
      (usePathname as jest.Mock).mockReturnValue('/');
    });

    afterEach(() => {
      jest.clearAllMocks();
    });

    it('should navigate to Orders page on click', () => {
      render(<LeftSideBar leftSideBarPathItems={leftSidebarItems} />);

      // 找到并点击Orders对应的li元素
      const liElement = screen.getByText('Orders').closest('li')!;
      fireEvent.click(liElement);

      // 断言push被正确调用
      expect(mockPush).toHaveBeenCalledWith('/Orders');
    });
  });
});

额外说明

  • 确保leftSidebarItems中对应Orders的path字段确实是'/Orders',否则断言会不匹配。
  • 若需要测试路由激活状态(比如当前路径匹配时的样式),可在beforeEach中修改usePathname的返回值,比如mockReturnValue('/Orders'),然后断言元素的className是否包含激活样式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:02:15