如何在React中使用Jest用可选链覆盖函数中的catch块?

问题描述 投票:0回答:1

我正在开发一个 React 项目,其中有一个使用可选链和 try-catch 块来分配导航函数的函数。我正在尝试编写一个 Jest 测试来覆盖 catch 块,但我很难触发它。代码如下:

    import { useNavigate } from 'react-router-dom';

let navigate;

function useNavigateMFE() {
  try {
    // Assign the navigate function based on the availability of the hfe properties.
    navigate = window?.hfe?.testdevice
      ? window?.hfe?.histr
      : useNavigate(); // Fallback to the standard useNavigate function if conditions are not met.
  } catch (e) {
    console.log("An error occurred:", e);
    // Optionally, provide a fallback action or handling in case of an error.
  }
}

// Call the function to set the navigate variable.
useNavigateMFE();

注意:每当组件渲染时都会触发

我尝试过的 我尝试了以下方法来覆盖 catch 块:

模拟 window.hfe 为 null 或未定义:这不会触发 catch 块,可能是因为可选链接可以防止抛出错误。 模拟useNavigate函数抛出错误:

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useNavigate: () => {
    throw new Error("Mocked error");
  },
}));

尽管如此,测试中仍然没有涵盖 catch 块。

我的目标 我想模拟一个触发 useNavigateMFE 函数中的 catch 块的错误。这是我当前测试用例的示例:

import { useNavigate } from 'react-router-dom';

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useNavigate: jest.fn(() => {
    throw new Error("Mocked error");
  }),
}));

describe('useNavigateMFE', () => {
  it('should enter the catch block when an error occurs', () => {
    // Spy on console.log to verify it was called
    const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {});

    // Act: Call useNavigateMFE to trigger the catch block
    useNavigateMFE();

    // Assert: Check that console.log was called
    expect(consoleSpy).toHaveBeenCalledWith(expect.any(Error));

    // Cleanup
    consoleSpy.mockRestore();
  });
});

问题 即使模拟的实现抛出错误,catch 块也不会被触发。如何确保我的测试覆盖了 catch 块?

附加信息 我正在使用 Jest 进行测试。 该代码是 React 项目的一部分。 任何意见或建议将不胜感激!

reactjs unit-testing react-hooks jestjs react-router
1个回答
0
投票

为了回答你的问题,通过查看代码,我相信你的方法应该有效,尽管当然,要抛出错误,你需要 both 模拟

window.hfe
null
并模拟
useNavigate
为抛出一个错误。目前尚不清楚你是否这样做了。另外,为了通过测试,您需要将
"An error occurred:"
添加到
.toHaveBeenCalledWith

但是

您需要重新考虑测试方法。基本上,您描述的测试是测试是否

try {
  throw new Error();
} catch (e) {
  console.log(e);
}

打印错误。是的,确实如此。它在语言规范中,您无需担心。

其他想法

  1. 您的挂钩无效。 hooks 规则规定您不能在条件或循环内调用 Hooks,而您正在使用
    useNavigate
    执行此操作。一个有效的替代方案是
const nav = useNavigate();
navigate = window?.hfe?.testdevice
  ? window?.hfe?.histr
  : nav;
  1. React 采用函数方法,将
    navigate
    作为函数外部的模块作用域变量违反了这一点,并且很难推断另一个函数是否也要修改该变量。最好从函数返回
    navigate
const nav = useNavigate();
return window?.hfe?.testdevice
  ? window?.hfe?.histr
  : nav;
© www.soinside.com 2019 - 2024. All rights reserved.