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

如何用Jest测试history.block的回调函数是否触发?

如何用Jest测试history.block的回调函数是否触发?

看起来你已经成功验证了history.block被调用,但回调里的逻辑(比如console.log)没触发,问题出在你用的mockhistory默认不会执行传入的回调函数,只是记录它被调用了而已。下面给你两种可行的测试思路:

方法一:手动保存并触发block的回调

首先我们需要让mock的history.block方法把传入的回调函数存下来,之后在测试里手动调用这个回调,这样就能验证里面的逻辑是否执行了。具体步骤如下:

  1. 先mockconsole.log,方便我们断言它是否被调用
  2. 创建一个带自定义block方法的mock history对象,保存传入的回调
  3. 渲染组件时把这个mock history传进去
  4. 触发导航操作后,手动调用保存的回调函数,最后断言结果

代码示例:

test('block navigation and fire console.log', async () => {
  // 监听console.log,避免真的输出到控制台,同时记录调用情况
  const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {});

  // 创建mock history对象,让block方法保存回调
  const mockHistory = {
    block: jest.fn((callback) => {
      // 把回调存到mockHistory上,方便后续调用
      mockHistory.blockCallback = callback;
      // 返回unblock函数(随便一个空mock就行)
      return jest.fn();
    }),
    push: jest.fn(), // 模拟push方法,对应你的导航操作
  };

  // 渲染组件,记得把mockHistory传给Router
  render(
    <Router history={mockHistory}>
      {/* 你的组件,包含触发导航的按钮 */}
      <button onClick={() => mockHistory.push('/target-route')}>Route</button>
      <YourComponent shouldBlock={true} />
    </Router>
  );

  // 点击导航按钮
  await userEvent.click(screen.getByText('Route'));

  // 模拟history.block收到的transition对象
  const mockTransition = {
    location: { pathname: '/target-route' },
  };

  // 手动调用block的回调函数
  mockHistory.blockCallback(mockTransition);

  // 断言console.log被正确调用(注意你原代码里的url可能是navigationUrl的笔误哦)
  expect(consoleLogSpy).toHaveBeenCalledWith('TEST: ', '/target-route');

  // 恢复console.log的原始行为
  consoleLogSpy.mockRestore();
});

方法二:让mock history自动触发block回调

如果你希望更贴近真实场景,也可以让mock的push方法自动触发block的回调,模拟真实的导航拦截流程:

test('block navigation triggers callback automatically', async () => {
  const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
  let blockCallback;

  const mockHistory = {
    block: jest.fn((callback) => {
      blockCallback = callback;
      return jest.fn();
    }),
    push: jest.fn((path) => {
      // 当调用push时,自动触发block回调
      blockCallback({
        location: { pathname: path },
        retry: jest.fn(), // 可以模拟retry方法,按需使用
      });
    }),
  };

  render(
    <Router history={mockHistory}>
      <button onClick={() => mockHistory.push('/target-route')}>Route</button>
      <YourComponent shouldBlock={true} />
    </Router>
  );

  await userEvent.click(screen.getByText('Route'));

  // 直接断言即可,不需要手动调用回调
  expect(consoleLogSpy).toHaveBeenCalledWith('TEST: ', '/target-route');
  consoleLogSpy.mockRestore();
});

小提示

你原代码里的console.log('TEST: ', url);可能是个笔误,应该用navigationUrl吧?不然url变量没定义,会报错哦。

备注:内容来源于stack exchange,提问作者marcus-linmarkson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 07:09:30