javascript 为什么我需要waitFor或act而不是在react测试中使用await?

mzillmmw  于 2023-05-12  发布在  Java
关注(0)|答案(1)|浏览(199)

1.我读到act / waitFor是等待DOM更新。我也读到渲染是同步的。我假设我不需要用act/waitFor Package Render,因为DOM总是在我单击或测试时更新?是这样吗?
1.接下来,我不明白为什么我需要act / waitFor?**我不能只做一个等待吗?**对于测试A,我使用user.click,我看到在线示例代码使用await。在我的笔记本电脑上似乎工作得很好。
然而在测试B中,当我看到www.example.com的一些示例代码fireEvent.click,他们使用waitFor。我尝试使用await,它标记我“await对这种类型的表达式没有影响”。但是“await waitFor()”可以工作。这是为什么呢?
非常感谢提前!

Test A
it('user.click', async () => {
  render(
    <BrowserRouter>
      <Notes />
    </BrowserRouter>
  );

  const checkBox = screen.getByRole('checkbox');
  await user.click(checkBox);
  const prev = screen.getByRole('button', { name: 'Prev' });
  expect(prev).toBeEnabled();
});

Test B
it('fireEvent.click', async () => {
  render(
    <BrowserRouter>
      <Notes />
    </BrowserRouter>
  );

  const checkBox = screen.getByRole('checkbox');
  await fireEvent.click(checkBox);
  const prev = screen.getByRole('button', { name: 'Prev' });
  expect(prev).toBeEnabled();
});
gwbalxhn

gwbalxhn1#

我尝试使用await,它标记我“await对这种类型的表达式没有影响”。但是“await waitFor()”可以工作。这是为什么呢?
await是将回调附加到promise的语法糖;一旦promise被解析或拒绝,异步函数的其余部分将继续执行。
例如,写await 3是没有意义的,因为3不是promise;没什么好等的。(实际上写await 3是法律的的,但它并没有真正完成任何事情;你可以写3
因此,await user.click(...)await waitFor(...)都很好,而await fireEvent.click(...)不好的原因是user.clickwaitFor都返回promise,而fireEvent.click没有。fireEvent.click只是调度事件并同步返回。(实际上,我也不确定user.click是否做了任何 * 固有 * 异步的事情-它似乎不依赖于任何像fetch这样的API-但可能测试库维护人员希望保持他们的选项开放,以防user.click真实的需要支持异步的东西。但是waitFor无论如何都必须是异步的,因为它的全部目的是每隔一段时间轮询一次回调,直到成功。
1.我读到act / waitFor是等待DOM更新。我也读到渲染是同步的。我假设我不需要用act/waitFor Package Render,因为DOM总是在我单击或测试时更新?是这样吗?
因此,有两种“异步”:

  • React通过排队microtasks异步完成了一些事情,比如应用状态更新;但这是React * 选择 * 做的事情,你可以使用act来解决它。具体而言:如果你把这些东西 Package 在act(() => { ... })中,那么React不会把微任务排队,而是把这些任务放在act拥有的一个特殊队列中,act将在返回之前执行这些任务。所以最终的结果是,从你的React组件的Angular 来看,任务仍然是异步的(例如,setState立即返回,实际上没有改变任何东西),但从你的测试代码的Angular 来看,它现在是同步的(所有这些更新都发生在act返回之前)。
  • 还有一些东西是异步的,因为它们依赖于真正的异步API,比如the Fetch API,React没有办法掩盖这一点;因此,您不能只使用act来完成这些操作,而是需要使用await来等待它们完成。
  • 有时候你会同时拥有这两个!如果你有一些异步的东西,然后导致对setState的调用(这是非常常见的-用异步获取的信息更新UI),那么await是不够的,因为setState(故意)不返回一个你可以等待的promise,它只是在幕后排队一些更改。在这种情况下,您需要编写await act(async () => { ... })。(act有特殊的逻辑使此工作;它检测到回调返回了一个promise,并确保在自己的promise解析之前执行React的所有异步逻辑。

现在你明白了,这个问题很容易回答:你不需要在render中使用act,因为render实际上在内部为你调用act;您不需要将awaitrender一起使用,因为渲染不涉及任何真正的异步API。所以你可以直接使用render

相关问题