Нестабильный асинхронный тест
Вопрос
Тест компонента с загрузкой данных иногда падает, а в консоли предупреждение «not wrapped in act». Как будешь разбираться?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Предупреждение значит: компонент обновился после окончания теста или вне ожидания
Жду результат через `findBy` или `waitFor`, а не `getBy` сразу
Проверяю, что все действия `user-event` с `await`
Убираю побочные действия из колбэка `waitFor`
Делаю ответы сети детерминированными через MSW, без реального API
Проверяю общие моки и состояние между тестами, сбрасываю обработчики после каждого теста
Что могут спросить следом
- Почему не стоит просто увеличить таймаут?
- Как тестировать debounce?
- Когда всё же нужно вызвать act вручную?
Разбор
Предупреждение про act почти всегда значит, что компонент ещё обновляется, когда тест уже сделал проверку или закончился. Например, ответ запроса пришёл позже, и setState случился вне ожидания.
Сначала проверяю, что тест ждёт результат: вместо getBy сразу после рендера использую await findBy или waitFor с проверкой. Затем смотрю на действия: у user.click и user.type должен быть await. В waitFor должна быть только проверка, иначе действие повторится несколько раз.
Дальше делаю ответы сети детерминированными через MSW и сбрасываю обработчики после каждого теста, чтобы один тест не влиял на другой. Если в коде есть таймеры, включаю фейковые часы и настраиваю user-event через advanceTimers.
Увеличивать таймаут не стану: это прячет проблему и замедляет набор тестов.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.