测试异步反应挂钩时应在哪里使用act?

时间:2019-07-19 11:21:29

标签: reactjs react-hooks react-hooks-testing-library

使用@testing-library/react-hooks测试异步反应挂钩时,我看到一条错误消息。错误消息中提到将代码包装在act(...)中,但是我不确定应该在哪里进行。

我尝试将部分代码包装在act(...)中,但是每次尝试都会导致测试失败。

// day.js 
import { useState, useEffect } from 'react';
import { getDay } from '../api/day';

export function useDay() {
  const [state, set] = useState({ loading: false });

  useEffect(() => {
    let canSet = true;

    set({ loading: true });
    const setDay = async () => {
      const day = await getDay();
      if (canSet) {
        set(day);
      }
    };

    setDay();

    return () => (canSet = false);
  }, []);

  return state;
}
// day.test.js
import { renderHook, act } from "@testing-library/react-hooks";
import { useDay } from "./day";

jest.mock("../api/day", () => ({
  getDay: jest.fn().mockReturnValue({ some: "value" })
}));

describe.only("model/day", () => {
  it("returns data", async () => {
    const { result, waitForNextUpdate } = renderHook(() => useDay());
    await waitForNextUpdate();
    expect(result.current).toEqual({ some: "value" });
  });
});
// test output
console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:102
      Warning: An update to TestHook 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 */

1 个答案:

答案 0 :(得分:1)

这是一个已知问题:https://github.com/testing-library/react-testing-library/issues/281

16.9.0-alpha.0之前,React本身不能很好地处理异步内容,因此与测试库无关。如果您对此感兴趣,请阅读该问题的评论。

您现在有两个选择:

  1. 将您的React(&react-dom)更新为16.9.0-alpha.0
  2. 添加一个代码段(例如,在您的测试设置文件中)以在console.log尝试打印该警告时取消显示该警告:

// FIXME Remove when we upgrade to React >= 16.9
const originalConsoleError = console.error;
console.error = (...args) => {
  if (/Warning.*not wrapped in act/.test(args[0])) {
    return;
  }
  originalConsoleError(...args);
};