Тестирование пользовательского хука и получение «Предупреждение: обновление TestHook внутри теста не было включено в действие - PullRequest
2 голосов
/ 15 июня 2019

РЕДАКТИРОВАТЬ: Я нашел решение, исходя из этого видео от Кента С. Доддса.

Просто оберните вызовы jest.advanceTimersByTime в функцию акта.

Итак, это:

jest.advanceTimersByTime(510);

становится:

act(()=>jest.advanceTimersByTime(510));

Я реализовал простой пользовательский хук, чтобы отменить обновление значения.

Вот код:

function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}

Клиент этого хука выглядит примерно так (очень упрощенно):

function Search(props) {
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearchTerm = useDebounce(searchTerm, 500);

  // doing something useful with debouncedSearchTerm....
  // ...
  // ...
}

Итак, я пытаюсь проверить ловушку с кодом ниже:

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

jest.useFakeTimers();

it.only('should update value after specified delay', () => {
  const { result, rerender } = renderHook(
    ({ value, delay }) => useDebounce(value, delay),
    { initialProps: { value: '', delay: 500 } }
  );

  expect(result.current).toBe('');
  jest.advanceTimersByTime(510);
  expect(result.current).toBe('');

  rerender({ value: 'Hello World', delay: 500 });

  expect(result.current).toBe('');
  jest.advanceTimersByTime(498);
  expect(result.current).toBe('');
  jest.advanceTimersByTime(3);
  expect(result.current).toBe('Hello World');
});

Хотя, тест пройден, я получаю следующее предупреждение:

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 */        This ensures that you're testing the behavior the user would see in the browser. Learn more at.....       in TestHook        in Suspense

Я понимаю, что если я собираюсь вызвать функцию для обновления внутреннего состояния ловушки (например, increment () ловушки useCounter), я должен сделать это в act функции, как указано в документации.

Но хук useDebounce, который я реализовал, изменяет состояние с помощью внутреннего useEffect, которое запускается всякий раз, когда изменяется значение или задержка.

Как мне избавиться от этого предупреждения? Что-то не так с моим кодом? Я забыл добавить что-нибудь в тестовый код?

Пожалуйста, помогите!

...