为什么我需要 waitFor 或 act 而不是在反应测试中只使用 wait ?

EBD*_*BDS 1 javascript testing unit-testing reactjs react-testing

  1. 我读到 act / waitFor 是等待 DOM 更新。我还读到渲染是同步的。我假设我不需要用 act/waitFor 包装渲染,因为当我单击或测试时 DOM 总是会更新?它是否正确 ?

  2. 接下来,我不明白为什么我需要 act / waitFor ? 我不能只是等待吗? 对于测试A,我使用user.click,并且我看到在线示例代码使用await。它似乎在我的笔记本电脑上运行良好。

    然而,在测试 B 中,当我看到 fireEvent.click 的一些示例代码时,他们使用了 waitFor。我尝试使用等待,它标记我“等待对这种类型的表达式没有影响”。但“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();
});
Run Code Online (Sandbox Code Playgroud)

rua*_*akh 5

\n

我尝试使用等待,它标记我“等待对这种类型的表达式没有影响”。但“await waitFor()”有效。为什么是这样 ?

\n
\n

await是用于将回调附加到 Promise 的语法糖;一旦承诺得到解决或拒绝,异步函数的其余部分将继续。

\n

因此,例如,编写类似 , 之类的内容是没有意义的await 3,因为3它不是承诺;没有什么可以等待的。(写实际上是合法的await 3,但它并没有真正完成任何事情;你可以只写3。)

\n

因此,await user.click(...)await waitFor(...)都很好,而 while 则await fireEvent.click(...)不然,因为user.clickwaitFor都返回承诺,而 whilefireEvent.click则不然。fireEvent.click只是调度事件并同步返回。(实际上我不确定这是否user.click会执行任何本质上异步的操作,无论是 \xe2\x80\x94 它似乎并不依赖于任何像fetch\xe2\x80\x94 这样的 API,但大概测试库维护者希望保留他们的选择open 以防真正需要支持user.click必须异步的东西。但waitFor无论如何,真正必须是异步的,因为它的全部目的是每隔一段时间轮询一次回调,直到成功为止。)

\n
\n
    \n
  1. 我读到 act / waitFor 是等待 DOM 更新。我还读到渲染是同步的。我假设我不需要用 act/waitFor 包装渲染,因为当我单击或测试时 DOM 总是会更新?它是否正确 ?
  2. \n
\n
\n

所以,有两种“异步”:

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

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

\n