【问题标题】:An update to TestHook inside a test was not w rapped in act(...)测试中对 TestHook 的更新未包含在 act(...) 中
【发布时间】:2020-05-04 06:30:48
【问题描述】:

我正在使用渲染 UI 组件的钩子并尝试对其进行测试。

import React, { useState, useCallback } from 'react';
import { useModal } from './useModal';
import { ConfirmationModal } from './common';

export const useConfirm = () => {
  // Manage if confirm module is open or close
  // Provide callback to set confirm state
  const { isShowing, toggle } = useModal();

  // Track confirmation module values
  const [confirmOptions, setConfirmOptions] = useState({});

  // Callback to set confirmation model properties
  const setConfirmation = useCallback(
    async (title, body, onConfirm, onCancel) => {
      await setConfirmOptions({
        title,
        body,
        onConfirm,
        onCancel
      });
      toggle();
    },
    [toggle]
  );

  const ConfirmModal = (
    <ConfirmationModal
      open={isShowing}
      toggle={toggle}
      title={confirmOptions.title}
      content={confirmOptions.body}
      onConfirm={confirmOptions.onConfirm}
      onCancel={confirmOptions.onCancel}
    />
  );

  return {
    setConfirmation,
    ConfirmModal
  };
};

测试:

import { renderHook, act } from '@testing-library/react-hooks';
import { useConfirm } from './useConfirm';

describe('useConfirm hook', () => {
  it('toggles confirm ui', () => {
    const { result } = renderHook(() => useConfirm());
    const onConfirm = jest.fn();
    const onCancel = jest.fn();
    // test confirm is called
    act(() => {
      result.current.setConfirmation(
        'Title',
        'Content Content',
        onConfirm,
        onCancel
      );

      console.log(result.current.ConfirmModal);
    });
    // test cancel is called
  });
});

我明白了:

Warning: An update to %s 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 react-hooks react-testing-library


【解决方案1】:

当您在组件完成所有状态更新之前尝试断言时,通常会发生此错误。

请注意,在 setConfirmation 内部,您正在调用 toggle(),这会更新状态。

您应该使用 waitFor 之类的东西来等待切换值更新或承诺已被调用。

我不熟悉render-hooks 库,但也许下面的示例可以帮助您。我还会在底部留下一些有用的链接。

  it('toggles confirm ui', async () => {
    const { result } = renderHook(() => useConfirm());
    const onConfirm = jest.fn();
    const onCancel = jest.fn();

    // test confirm is called    
    result.current.setConfirmation(
      'Title',
      'Content Content',
      onConfirm,
      onCancel
    );

    await waitFor(() => expect(onConfirm).toHaveBeenCalled());
    // or await for something to appear on the screen
  });

React 中的act() 是什么docs

在编写 UI 测试时,渲染、用户事件或数据获取等任务可以被视为与用户界面交互的“单元”。 React 提供了一个名为 act() 的帮助器,它确保在您做出任何断言之前,与这些“单元”相关的所有更新都已被处理并应用于 DOM。

名称 act 来自 Arrange-Act-Assert 模式。


有用的链接:

【讨论】:

    【解决方案2】:

    这个问题可能是由动画引起的,在这种情况下,您可以通过使用 Jest 模拟计时器来解决问题:

    describe('...', () => {
      beforeAll(() => {
        jest.useFakeTimers();
      });
    
      afterAll(() => {
        jest.useRealTimers();
      });
      // ...
    });
    

    【讨论】:

      猜你喜欢
      • 2022-11-25
      • 1970-01-01
      • 2021-01-14
      • 1970-01-01
      • 2019-10-29
      • 2020-12-13
      • 2021-09-12
      • 1970-01-01
      • 2019-08-06
      相关资源
      最近更新 更多