Asyn c тестирование React Navigation 5 в Jest: NavigationContainer вызывает ошибку консоли - PullRequest
5 голосов
/ 09 мая 2020

Я использую react-native-testing-library и после обновления react-navigation с 4 до 5, я выполнил следующие инструкции: https://callstack.github.io/react-native-testing-library/docs/react-navigation, чтобы обновить большую часть моего набора тестов.

Итак пока все хорошо. Суть здесь в том, чтобы обернуть ваши тесты в NavigationContainer, чтобы мои компоненты имели доступ к тем хукам, которые ранее были получены из react-navigation-hooks.

Это отлично работает, когда мои тесты синхронны, но как только я добавив ключевое слово async к функции тестирования, я получаю следующее предупреждение:

console.error
    Warning: An update to ForwardRef(NavigationContainer) 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 https://reactjs.org/docs/test-utils.html#act
        in ForwardRef(NavigationContainer)

Есть множество тестов, которые я запускаю синхронно и успешно. Но в некоторых компонентах я запускаю некоторые asyn c logi c, чтобы получить желаемый результат.

Насколько я понимаю, я должен заключить любой asyn c код в вызов act. Однако даже в этом случае я не могу избавиться от этой ошибки.


Я попытался сузить проблему. Теперь все, что я делаю, это визуализирую обернутый компонент следующим образом:

test('a simple test', async () => {
  const component = (
    <NavigationContainer>
      <AppNavigator />
    </NavigationContainer>
  );

  const {queryByText} = render(component);
  expect(queryByText('test')).toBeNull();
});

И я все еще сталкиваюсь с той же проблемой. Имейте в виду, что фактический тест проходит успешно, только я все еще получаю эту консольную ошибку.

Затем я попытался обернуть вызов render в act и waitForElement, потому что это то, что я ' m должен делать при запуске asyn c logi c. Но похоже, что здесь выполняется асинхронный c код после рендеринга.

Итак, я продолжил исследовать, какая часть NavigationContainer отвечает за запуск asyn c logi c, ответственного за ошибку, и кажется, что этот фрагмент кода (строка 49-51) делает что-то интересное:

const [isReady, initialState = rest.initialState] = useThenable(
  getInitialState
);

getInitialState является результатом деструктуризации возвращаемого значения вызова useLinking за несколько строк до (43-47). Не вдаваясь в дальнейшие подробности, getInitialState заключен в обещание, поэтому он становится «применимым».

Теперь, если я раскомментирую useThenable, ошибка консоли исчезнет. Но очевидно, что это не то, чего я могу легко добиться вне этого файла. Итак, я немного застрял здесь, потому что я не знаю, как написать свой тестовый код асинхронным c способом, не сталкиваясь все время с этой ошибкой, и мне не хочется игнорировать или подавлять ее, это хорошо идея тоже.

Любая помощь приветствуется.

1 Ответ

7 голосов
/ 11 мая 2020

Моя рекомендация после вызова render из react-native-testing-library для компонентов, которые выполняют асинхронную c работу, useEffect (действуя как componentDidMount), меняют состояние и т. Д. c:

await act(async () => {})

Или даже:

await act(async () => await flushMicrotasksQueue())

Если у вас есть таймауты.

...