【问题标题】:Cannot test custom hooks with React 18 and renderHook from testing-library/react无法使用 React 18 和来自 testing-library/react 的 renderHook 测试自定义钩子
【发布时间】:2022-08-18 07:14:03
【问题描述】:

我有一个自定义钩子,它在 mount 上调用 API 并处理状态(isLoading、isError、date、refetch);

钩子很简单:

    const useFetch = (endpoint, options) => {
    const [data, setData] = useState(null);
    const [error, setError] = useState(null);
    const [isLoading, setIsLoading] = useState(true);
    const [trigger, setTrigger] = useState(true);

    const triggerSearch = () => {
        setTrigger(!trigger);
    };

    useEffect(() => {
        const fetchData = async () => {
            try {
                const response = await fetch(
                    `${process.env.API_URL}${endpoint}`
                );
                const json = await response.json();
                setData(json);
                setIsLoading(false);
            } catch (error) {
                setError(error);
                setIsLoading(false);
            }
        };
        fetchData();
    }, [endpoint, trigger]);
    return {
        data,
        isLoading,
        error,
        triggerSearch,
    };
};

在尝试测试钩子时,我正在使用 jest 和 testing-library/react。

使用 react 18,不再支持 testing-library 中的 react-hooks,因此我不能使用 renderHook 中的 awaitForNextUpdate,因为它不会返回它。

相反,我们应该使用 act 和 waitFor - 我已经完成并且测试通过了。

问题是我收到以下错误

警告:测试中对 TestComponent 的更新未包含在 行为(...)。

When testing, code that causes React state updates should be wrapped into act(...):
test(\"should make an API call on mount\", async () => {
    const hook = renderHook(() => useFetch(\"/api\"));

    await act(async () => {
        await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));
    });

    expect(fetch).toHaveBeenCalledTimes(1);

    expect(getAccessTokenSilently).toHaveBeenCalledTimes(1);

    expect(hook.result.current.data).toEqual({ message: \"Test\" });
    expect(hook.result.current.isLoading).toEqual(false);
    expect(hook.result.current.error).toEqual(null);
});

有人可以指出我正确的方向吗?我尝试删除所有断言并仅调用 renderHook,这也会导致相同的错误。

  • 嘿,我现在发现了同样的问题,因为我已经更新到 React 18 和最新的 RTL 13.3 和 jest 5.16.5。您找到任何解决方案了吗?

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


【解决方案1】:

这样的事情可能会奏效。

test("should make an API call on mount", async () => {
  const hook = renderHook(() => useFetch("/api"));

  // remove the act method
  // you are not triggering an user action
  await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));

  expect(getAccessTokenSilently).toHaveBeenCalledTimes(1);

  expect(hook.result.current.data).toEqual({ message: "Test" });
  expect(hook.result.current.isLoading).toEqual(false);
  expect(hook.result.current.error).toEqual(null);
});

或者您可以尝试推进计时器:

beforeAll(() => {
  // we're using fake timers because we don't want to
  // wait a full second for this test to run.
  jest.useFakeTimers();
});

afterAll(() => {
  jest.useRealTimers();
});

test("should make an API call on mount", () => {
  const hook = renderHook(() => useFetch("/api"));

  //advance timers by 1 second
  jest.advanceTimersByTime(1000);

  // remove the act method
  // you are not triggering an user action
  expect(fetch).toHaveBeenCalledTimes(1);

  expect(getAccessTokenSilently).toHaveBeenCalledTimes(1);

  expect(hook.result.current.data).toEqual({ message: "Test" });
  expect(hook.result.current.isLoading).toEqual(false);
  expect(hook.result.current.error).toEqual(null);
});

在我的情况下,我使用点击事件来更新 DOM,我必须在 fireEvent 点击事件期间使用 act,如下所示:

 it('open toggler assessment modal when clicking card button', async () => {
    renderTeacherAssessments();

    const assessmentCard = screen.getAllByTestId('assessment-card');
    const assessmentCardButton = assessmentCard[0].querySelector('button');

    act(() => {
      assessmentCardButton.click();
    });

    await waitFor(() => {
      expect(screen.getByTestId('confirm-modal')).toBeInTheDocument();
    });
  });

我在其他帖子中阅读过有关act 警告的内容,其中大多数问题将通过使用await waitFor... 包装expect 方法来修复,但现在对于React18 和最新的RTL,我不确定它是否仍然有效.

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 2021-04-25
    • 1970-01-01
    • 2021-10-22
    • 2019-12-21
    • 1970-01-01
    • 2022-07-15
    • 2021-10-10
    • 2022-12-29
    相关资源
    最近更新 更多