React-testing-library 的 renderHook 的 WaitForNextUpdate 超时

sim*_*bon 12 unit-testing reactjs react-testing-library react-hooks

我正在测试一个自定义挂钩,react-testing-library它基本上可以执行以下操作:

function useHook() {
  const [state, setState] = useState();
  
  const fetch = async () => {
    const response = await httpCall();
    if (instanceof response !== Error) {
      setState("GOOD")
    } else {
      setState("BAD")
    }
  }
  
  return { state, fetch }
}
Run Code Online (Sandbox Code Playgroud)

我的测试文件是这样的:

it("test", async () => {
  const { result, waitForNextUpdate } = renderHooks(() => useHook())

  await result.current.fetch();
  expect(result.current.state).toBe(undefined)

  await waitForNextUpdate();
  expect(result.current.state).toBe("GOOD") //or at least "BAD"
})
Run Code Online (Sandbox Code Playgroud)

我写这个是因为我调用了应该触发 setState 的异步函数fetch(),我断言尚未发生重新渲染,然后waitForNextUpdate()为了等待此重新渲染,我断言state钩子返回的值现在具有值"GOOD""BAD"

我的问题是我的测试给了我一个错误:Timeout - Async callback was not invoked within the 5000 ms ...,并且当测试等待waitForNextUpdate().

我不知道我的测试出了什么问题。我确信(因为我测试过)该钩子工作正常,http 调用已经完成。我知道检查测试内的值,但也是因为挂钩在应用程序内正常工作。我不明白为什么状态似乎从未发生过更新。

我是我的团队中第一个使用这个工具进行测试的人,所以我很迷失。

小智 1

await在调用钩子测试下的函数时不应使用。

相反,它应该包含在 中act(),尽管根据有关异步测试的文档await waitForNextUpdate()中的指定,在调用时可以省略它。

测试通过此更改:

it('test', async () => {
  const { result, waitForNextUpdate } = renderHook(() => useHook());

  act(() => {
    result.current.fetch();
  });
  expect(result.current.state).toBe(undefined);

  await waitForNextUpdate();
  expect(result.current.state).toBe('GOOD'); //or at least "BAD"
});
Run Code Online (Sandbox Code Playgroud)

  • 你的答案缺少导入语句,这在这里非常重要,因为有几个不同的反应测试库具有“renderHook”函数。但是,并非所有这些“renderHook”版本都返回“waitForNextUpdate”函数。 (3认同)