Я продолжаю получать Warning: An update to App inside a test was not wrapped in act(...). в своем наборе тестов всякий раз, когда делаю запрос API и обновляю состояние.
Я использую библиотеку тестирования реакции. Я также пробовал использовать тестовые утилиты ReactDOM, получил тот же результат. Еще одна вещь, которую я попробовал, это обернуть контейнер в act, но все равно получил тот же результат.
Обратите внимание, что: Мое приложение работает, и мой тест проходит. Мне просто нужно знать, что я делал неправильно, или это ошибка в пакете react-dom, из-за которой появляется эта ошибка. И плохо издеваться над ошибкой консоли и заглушать ее.
global.fetch = require('jest-fetch-mock');
it('should clear select content item', async () => {
fetch.mockResponseOnce(JSON.stringify({ results: data }));
const { container } = render(<App />);
const content = container.querySelector('.content');
await wait();
expect(content.querySelectorAll('.content--item').length).toBe(2);
});
Вот реализация хука:
const [data, setData] = useState([]);
const [error, setError] = useState('');
const fetchInitData = async () => {
try {
const res = await fetch(API_URL);
const data = await res.json();
if (data.fault) {
setError('Rate limit Exceeded');
} else {
setData(data.results);
}
} catch(e) {
setError(e.message);
}
};
useEffect(() => {
fetchInitData();
}, [isEqual(data)]);
Да это оно. Позвольте мне добавить, что это работает, и мой тест проходит. Единственная проблема - это раздражающие ошибки





Это известная проблема, проверьте эту проблему в Github https://github.com/kentcdodds/react-testing-library/issues/281.
Чтобы избавиться от предупреждения act(), вам нужно убедиться, что ваши промисы разрешаются синхронно. Вы можете прочитать здесь, как это сделать.
Резюме:
The solution for this is a bit involved:
- we polyfill Promise globally with an implementation that can resolve promises 'immediately', such as promise
- transpile your javascript with a custom babel setup like the one in this repo
- use jest.runAllTimers(); this will also now flush the promise task queue
У меня была эта проблема, и я отказался от ожидания и асинхронности, вместо этого использовал шутливые поддельные таймеры и т. д., поэтому ваш код должен быть примерно таким.
global.fetch = require('jest-fetch-mock');
it('should clear select content item', /*async */ () => {
jest.useFakeTimers();
fetch.mockResponseOnce(JSON.stringify({ results: data }));
const { container } = render(<App />);
const content = container.querySelector('.content');
// await wait();
act(() => {
jest.runAllTimers();
});
expect(content.querySelectorAll('.content--item').length).toBe(2);
});Для всех, кто наткнется на это больше года спустя, как и я, проблема, о которой упоминает Джорджио, с тех пор решена, и с тех пор wait заменен на waitFor, как описано здесь:
https://testing-library.com/docs/dom-testing-library/api-async/
В этом случае я считаю, что решение для предупреждения сейчас должно быть примерно таким:
import { render, waitFor } from '@testing-library/react';
// ...
it('should clear select content item', async () => {
fetch.mockResponseOnce(JSON.stringify({ results: data }));
const { container } = render(<App />);
const content = container.querySelector('.content');
await waitFor(() =>
expect(content.querySelectorAll('.content--item').length).toBe(2);
);
});
В моем случае у меня был компонент App, который асинхронно загружал данные в хук useEffect, поэтому я получал это предупреждение при каждом отдельном тесте, используя beforeEach для рендеринга App. Это было конкретное решение для моего случая:
beforeEach(async () => {
await waitFor(() => render(<App />));
});
Это все внутри функции?