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

如何在Storybook中断言nextRouter.push动作已触发?

问题解决:Storybook中断言Next.js router.push调用失败的修复

错误原因

你使用action('nextRouter.push')创建的是一个全新的action实例,并非Storybook用来记录路由调用的那个mock/spy函数,因此Jest的toHaveBeenCalledWith断言无法识别它,导致报错。


解决方案一:复用Storybook自动注册的action spy

@storybook/nextjs会自动将nextRouter的方法注册为Storybook actions,这些action的spy实例可以通过Storybook的内部通道获取:

import { within, fireEvent } from '@storybook/testing-library';
import { expect } from '@storybook/jest';

export const Default: Story = {
  play: async (args) => {
    const canvas = within(args.canvasElement);
    // 触发组件变更事件
    fireEvent.change(canvas.getByTestId('my-component'), {
      target: { value: 'AMSTERDAM' },
    });

    // 获取Storybook的actions通信通道
    const channel = window.__STORYBOOK_ADDONS_CHANNEL__;
    // 取出nextRouter.push对应的spy函数
    const routerPushSpy = channel.getAction('nextRouter.push');
    
    // 执行断言
    expect(routerPushSpy).toHaveBeenCalledWith('/stays/amsterdam');
  },
};

解决方案二:手动mock useRouter钩子(更适合CI环境)

直接在Story中mock Next.js的useRouter钩子,完全控制路由行为,避免依赖Storybook内部API,稳定性更高:

import { within, fireEvent } from '@storybook/testing-library';
import { expect, jest } from '@storybook/jest';
import { useRouter } from 'next/router';

// 全局mock useRouter
jest.mock('next/router', () => ({
  useRouter: jest.fn(),
}));

export const Default: Story = {
  beforeEach: () => {
    // 每次用例前重置mock,避免用例间污染
    const mockPush = jest.fn();
    (useRouter as jest.Mock).mockReturnValue({
      push: mockPush,
      // 按需添加其他router属性(如pathname、query等)
    });
  },
  play: async (args) => {
    const canvas = within(args.canvasElement);
    fireEvent.change(canvas.getByTestId('my-component'), {
      target: { value: 'AMSTERDAM' },
    });

    // 获取mock的push方法并断言
    const mockPush = (useRouter as jest.Mock).mock.results[0].value.push;
    expect(mockPush).toHaveBeenCalledWith('/stays/amsterdam');
  },
};

方案对比

  • 方案一:无需额外mock,复用Storybook自动生成的路由模拟,但依赖Storybook内部实现,兼容性可能随版本变化。
  • 方案二:完全独立,不依赖Storybook内部机制,断言逻辑更清晰,适合CI环境长期运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 13:18:24