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

如何测试先挂起后抛出错误的React Hook?

测试先挂起后抛出错误的React Hook

常规Hook错误测试方法

用react-testing-library的renderHook结合expect和toThrowError,可以测试普通Hook在特定条件下的抛出错误行为,示例代码:

it("throws an error", async () => {
  expect(
    () => renderHook(() => usePizza(), { wrapper })
  ).toThrowError("oops");
});

这种方式对普通Hook有效,但如果Hook在抛出错误前会先挂起(比如使用了Suspense),常规方法就失效了。

带Suspense的Hook示例

以下Hook会先通过use挂起等待Promise完成,再根据参数抛出错误:

export const usePizzaWithSuspense = (clumsy) => {
  const pizza = use(bakedPizza); // 此处挂起等待Promise
  if (clumsy) {
    throw new Error("oops I dropped it");
  }
  return `mmm: ${pizza}`;
};

const bakedPizza = new Promise((resolve) =>
  setTimeout(() => resolve("delicious pizza"), 100)
);

常规测试方法失效的情况

用之前的写法测试这个Hook时,错误无法被捕获:

it("throws an error", async () => {
  expect(
    () => renderHook(() => usePizzaWithSuspense(true), { wrapper })
  ).toThrowError("oops");
});

正确的测试方法

因为Hook先挂起,错误会在Promise解决后才抛出,所以需要异步等待挂起结束,再检查Hook的错误结果:

it("throws an error after suspense", async () => {
  const { result, waitForNextUpdate } = renderHook(
    () => usePizzaWithSuspense(true),
    { wrapper: ({ children }) => <Suspense fallback={null}>{children}</Suspense> }
  );

  // 等待挂起完成,此时Hook会抛出错误
  await waitForNextUpdate();

  // 检查错误是否匹配
  expect(result.error).toMatch("oops I dropped it");
});

原理是:renderHook返回的result.error会存储Hook抛出的错误,而waitForNextUpdate会等待Hook完成挂起状态的更新,此时错误已经被捕获到result.error中,直接断言即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 11:06:01