React Testing Library中waitFor与act的区别及异步测试写法咨询
你当前的写法不合规,仅凑巧能跑通,存在逻辑隐患
waitFor的核心逻辑是重复执行内部回调,直到回调不抛出错误/达到超时时间,你把Demo.triggerCallback()放在waitFor内部,会导致这个方法被反复执行多次,不符合单测单次触发操作的预期,也会给后续复杂逻辑的测试埋下隐患。另外你额外加的try/catch完全多余,Jest本身会捕获断言错误并标记用例失败,不需要手动处理。
正确的写法如下:
异步场景下,先触发异步操作,再用waitFor包裹断言,等待期望结果出现即可:
it("test", async () => { const Demo = new Demo(); render(<DemoComponent Demo={Demo}/>); // 先触发更新操作 void Demo.triggerCallback(); // 用waitFor等待期望的视图更新完成 await waitFor(() => { expect(screen.getByText("Foo")).toBeInTheDocument(); }); });
act和waitFor的适用场景区别
act
是React测试工具提供的基础API,作用是告知React:接下来要执行会触发状态更新的操作,让React把所有同步的状态更新、副作用执行、DOM渲染都处理完毕后,再退出act的回调执行后续逻辑。
注意:React 17及更早版本的act不支持异步回调,这就是你之前写async () =>传入act报错的原因;React 18已经支持异步act,可以传入async回调。
适用场景:所有同步的状态更新操作,比如点击按钮、输入内容、调用同步的状态修改方法等。waitFor
是React Testing Library封装的异步断言工具,内部已经自动集成了act的能力,会自动把回调内触发的状态更新用act包裹,同时支持轮询判断断言是否成立。
适用场景:所有需要等待异步操作落地的场景,比如接口请求返回、定时器触发、异步回调执行后才会更新的状态断言。
补充可选方案
如果你使用的是React 18及以上版本,直接用异步act的写法也是合规的,不用依赖waitFor:
it("test", async () => { const Demo = new Demo(); render(<DemoComponent Demo={Demo}/>); await act(async () => { await Demo.triggerCallback(); }); expect(screen.getByText("Foo")).toBeInTheDocument(); });
内容的提问来源于stack exchange,提问作者hanuruh
相关产品推荐
相关产品推荐

