【问题标题】:Jest + react-testing-library: Warning update was not wrapped in act()Jest + react-testing-library:警告更新未包含在 act() 中
【发布时间】:2019-08-06 10:32:34
【问题描述】:

我正在使用 react-testing-library 测试我的组件,并且测试效果很好。我只是无法摆脱这个警告,fireEvent 应该被包装在开箱即用的行为中,但我试图再次包装它并没有帮助。

这是我的测试用例。

it.only("should start file upload if file is added to the field", async () => {
    jest.useFakeTimers();
    const { getByTestId } = wrapper;
    const file = new File(["filefilefile"], "videoFile.mxf");

    const fileInput = getByTestId("drop-zone").querySelector(
      "input[type='file']"
    );

    fireEvent.change(fileInput, { target: { files: [file] } });

    act(() => {
      jest.runAllTimers();
    });

    await wait(() => {
      expect(
        initialProps.uploadItemVideoFileConnect.calledWith(file, 123)
      ).toBe(true);
    });
  });

这里是警告

Warning: An update to UploadButtonGridComponent inside a test was not wrapped in act(...).

    When testing, code that causes React state updates should be wrapped into act(...):

    act(() => {
      /* fire events that update state */
    });
    /* assert on the output */

【问题讨论】:

标签: javascript reactjs jestjs react-testing-library


【解决方案1】:

在source code 中,fireEvent 已经包裹在act() 中。

问题可能与这个问题有关,其中异步逻辑(例如useEffect)正在触发fireEvent之外的状态更改:

https://github.com/kentcdodds/react-testing-library/issues/281

(如果没有看到您的组件实现,很难确定这是否正是您的情况。)

显然有计划在未来的版本中包含异步处理,这样就不会成为问题。

【讨论】:

【解决方案2】:

在act 之前添加await

await act(() => {
      /* fire events that update state */
    });

【讨论】:

  • 实际中的匿名函数必须是异步的,等待才能生效。 await act(async()=>{ //做你的事})
【解决方案3】:

这个问题是由组件内部的许多更新引起的。

我也一样,这就是我解决问题的方法。

await act( async () => {
 fireEvent.change(fileInput, { target: { files: [file] } });
});

【讨论】:

  • 请注意,如果您有两个相邻的 fireEvent,则需要两个 act(),每个一个。
  • 这给了我Warning: You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);
  • 此解决方案解决了我在测试输入 Formik 表单的组件时遇到的问题。我收到此警告:警告:测试中对 Formik 的更新未包含在 act(...) 中
  • 这在渲染触发内部状态更改的组件时也很有帮助
【解决方案4】:

所以这很难总结,但我会尝试。

act 警告只是告诉您,您的功能组件中发生了一些您没有测试的事情。

假设我们正在像这样渲染一个待办事项列表

    <ul>
      {loading ? (
        <p>Fetching todos</p>
      ) : (
        <>
          {appData.todoList.slice(0, 15).map((item) => {
            const { id, title } = item;
            return (
              <li key={id} data-testid={id}>
                <Link to={`/item/${id}`}>{title}</Link>
              </li>
            );
          })}
        </>
      )}
    </ul>

下面的测试用例会抛出act警告

import { waitFor, screen, waitForElementToBeRemoved } from "@testing-library/react";

it("Renders <TodoList /> component", async () => {
    render(<TodoList />);
    await waitFor(() => expect(axios.get).toHaveBeenCalledTimes(1));
    await waitForElementToBeRemoved(() => screen.getByText(/Fetching todos/i));

    expect(axios.get).toHaveBeenCalledTimes(1);
    todos.slice(0, 15).forEach((td) => {
      expect(screen.getByText(td.title)).toBeInTheDocument();
    });
  });

但是如果你像这样重新排序await 行

await waitForElementToBeRemoved(() => screen.getByText(/Fetching todos/i));
await waitFor(() => expect(axios.get).toHaveBeenCalledTimes(1);

act 警告消失。这是有道理的。您必须确保您的用户不再看到加载指示器。

还有其他情况,请继续阅读 kent Dodds 的这篇文章。

https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning

【讨论】:

    猜你喜欢
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 2020-03-26
    相关资源
    最近更新 更多