如何测试先挂起后抛出错误的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
相关产品推荐
相关产品推荐

