如何使用 Jest 部分模拟自定义反应钩子?

时间:2021-06-03 13:38:27

标签: reactjs unit-testing jestjs react-hooks mocking

我想用 Jest 模拟我的一些自定义 React 钩子返回值。 这是我正在尝试做的一个例子:

export default function useSongPlayer() {
  const playSongA = () => {...}
  const playSongB = () => {...}
  const playSongC = () => {...}

  return {
    playSongA,
    playSongB,
    playSongC,
  }
}

现在在我的测试中,我只想模拟 playSongA 并保持其他函数的真实实现。我尝试了几种方法,包括使用 jest.requireActual('hooks/useSongPlayer') 进行处理,但似乎 playSongA 已成功模拟,而其他方法尚未定义。

有了这样的东西,我很确定能达到我想要的

export function playSongA() {...}

export function playSongB() {...}

export function playSongC() {...}

问题似乎是我尝试模拟的模块是一个函数,我想部分模拟这个函数的结果。

1 个答案:

答案 0 :(得分:0)

如果您创建一个返回原始值但同时拦截函数调用并替换其中一个值的模拟,这是可能的。

您可以在没有 Proxy 的情况下执行此操作,但我选择演示它,因为它是拦截任何实际钩子使用的最完整方法。

hooks/__mocks__/useSongPlayer.js

// Get the actual hook
const useSongPlayer = jest.requireActual('hooks/useSongPlayer');

// Proxy the original hook so everything passes through except our mocked function call
const proxiedUseSongPlayer = new Proxy(useSongPlayer, {
  apply(target, thisArg, argumentsList) {
    const realResult = Reflect.apply(target, thisArg, argumentsList);
    return {
      // Return the result of the real function
      ...realResult,
      // Override a single function with a mocked version
      playSongA: jest.fn(),
    };
  }
});

export default proxiedUseSongPlayer;