React testing: 18 сложных вопросов, которые реально задают на интервью
18 сложных вопросов по тестированию React: StrictMode, Suspense, optimistic update, fake timers, MSW, accessibility, cache и границы между component, integration и e2e.
- Введение
- Как читать эту подборку
- Архитектура тестового слоя: где проходит разумная граница
- Таблица выбора: какой уровень теста нужен сценарию
- 18 сложных вопросов по React testing
- 1. Как понять, что сценарий вообще не должен жить в component test?
- 2. Что в тестировании React реально меняет StrictMode, а что нет?
- 3. Как тестировать debounced поиск так, чтобы не привязаться к таймингам?
- 4. Как тестировать optimistic update, чтобы сценарий был неполным без rollback?
- 5. Когда fake timers полезны, а когда они ломают доверие к тесту?
- 6. Как правильно тестировать Suspense, чтобы не тестировать внутреннюю магию библиотеки?
- 7. Что именно нужно проверить в модальном окне кроме самого факта открытия?
- 8. Как тестировать accessibility у сложных виджетов, а не только у кнопок и инпутов?
- 9. Когда integration-тест должен мокать сеть, а когда лучше идти в e2e?
- 10. Почему тест на React Query или другой cache layer легко становится ложноположительным?
- 11. Как тестировать URL-состояние фильтров без избыточного e2e?
- 12. Что плохого в тесте, который знает слишком много про renderWithProviders?
- 13. Как тестировать server error так, чтобы сценарий не заканчивался на сообщении об ошибке?
- 14. Какой вопрос про mocks сразу отделяет зрелый тестовый подход от поверхностного?
- 15. Как проверить, что тест устойчив к безопасному рефакторингу?
- 16. Как тестировать поведение после повторного mount, если баг проявляется только так?
- 17. Что интервьюер хочет услышать в вопросе про покрытие тестами, кроме слова coverage?
- 18. Как бы вы объяснили разницу между хорошим React-тестом и просто проходящим React-тестом?
- Код-пример: как проверять optimistic UI и rollback на integration-уровне
- Production pitfalls: где такие вопросы чаще всего ломают кандидатов
- 1. Кандидат отвечает инструментом вместо модели риска
- 2. Асинхронность маскируют таймингами
- 3. Accessibility сводят к формальной проверке роли
- Разбор производительности тестового слоя
- Практики, которые делают ответы и тесты сильнее
- Как отвечать на интервью
- FAQ
- Нужно ли на такие вопросы всегда отвечать через Jest или Vitest?
- Стоит ли учить наизусть API Testing Library перед интервью?
- Что чаще всего делает ответ слабым даже у опытного разработчика?
- Нормально ли в ответе признавать trade-off и ограничения?
- Если опыта с Suspense или optimistic update мало, как не провалиться?
- Итоги
Введение
Подборки вопросов по React часто уходят либо в базу вроде "что такое Testing Library", либо в пересказ любимого стека команды. На реальном интервью проверяют, какой риск закрывает тест, где проходит граница между UI-контрактом и внутренней реализацией, как ведет себя интерфейс при гонках, кеше, Suspense, ошибках сети и сложной доступности. Если этого слоя нет, кандидат знает инструменты, но не умеет проектировать надежный тестовый слой.
Внутри React-кластера эта тема уже разложена по нескольким направлениям: есть общий материал про то, как React тестирование выстраивается как система уровней и рисков, есть практический разбор Jest + React Testing Library без хрупких тестов и отдельная статья про то, что такое component tests, UI-контракты, состояния и доступность. Эта подборка не дублирует их. Здесь собраны 18 других вопросов, которые удобны именно для тренировки middle-level ответа.
Больше вопросов в Telegram
Ежедневные разборы и реальные кейсы с интервью
Как читать эту подборку
Ниже вопросы сгруппированы не по библиотекам, а по типу инженерного решения.
| Блок | Что проверяют | Где кандидаты чаще всего теряют баллы |
|---|---|---|
| Граница теста | Понимаете ли вы, почему сценарий вообще живет на этом уровне | Отвечают шаблоном "я бы написал unit-тест" без привязки к риску |
| Асинхронный UI | Умеете ли вы работать с loading, retry, cancelation и гонками | Лечат нестабильность waitFor и таймерами |
| Данные и кэш | Понимаете ли вы optimistic update, rollback и refetch | Проверяют только happy path и забывают о рассинхронизации |
| Accessibility | Видите ли вы keyboard flow, focus management и роли сложных виджетов | Сводят доступность к getByRole без сценария |
| Современный React | Учитываете ли вы StrictMode, Suspense и границы client/server логики | Переносят старые тестовые привычки на новую модель без поправок |
Архитектура тестового слоя: где проходит разумная граница
На большом React-проекте тесты почти никогда не становятся хрупкими из-за одной плохой библиотеки. Обычно проблема архитектурная: один и тот же сценарий одновременно пытаются защитить unit-тестом, component-тестом и e2e, а рядом остаются незащищенными реальные риски вроде rollback после mutation, утери фокуса в модальном окне или ошибки при refetch. Поэтому хороший ответ на интервью начинается не с инструмента, а с карты слоев.
Рабочая схема обычно выглядит так:
- Чистая доменная логика, преобразования и state transitions живут отдельно и проверяются дешевыми unit-тестами.
- Компонентный тест защищает локальный UI-контракт: роли, состояния, клавиатуру, смену активной панели, disabled/error/loading.
- Integration-тест проверяет связку нескольких слоев: роут, query cache, форму, mutation, обработку серверной ошибки, optimistic UI.
- E2E держит только несколько дорогих бизнес-путей: логин, checkout, критичный wizard, оплата, восстановление после ошибки.
Если эта граница расплылась, тесты начинают спорить друг с другом. Когда нужно глубже понять, почему это связано с устройством самого фронтенда, полезно держать рядом разбор архитектуры больших React-приложений и материал про client state vs server state в React.
Таблица выбора: какой уровень теста нужен сценарию
| Сценарий | Component test | Integration test | E2E |
|---|---|---|---|
Tabs, Dialog, Combobox, keyboard navigation | Да | Иногда | Редко |
| Форма с загрузкой данных и submit | Частично | Да | Иногда |
| Оптимистическое обновление списка | Нет | Да | Иногда |
| Поведение query cache после refetch | Нет | Да | Редко |
| Маршрут с авторизацией, redirect и persisted state | Нет | Частично | Да |
| Платежный или onboarding-flow | Нет | Частично | Да |
| Чистый formatter или reducer | Нет | Нет | Нет |
Эта таблица полезна не как догма, а как фильтр от лишнего шума. Если вы отвечаете на вопрос "как бы вы тестировали X", сильнее всего звучит не название инструмента, а объяснение, почему сценарий находится именно на этом уровне.
18 сложных вопросов по React testing
1. Как понять, что сценарий вообще не должен жить в component test?
Если поведение зависит от роутера, query cache, нескольких провайдеров и серверного ответа, компонентный тест быстро начинает притворяться integration-тестом. Это узнается по симптомам: нужен огромный renderWithProviders, нужно поднимать полприложения, а половина ожиданий касается уже не локального контракта компонента, а поведения экрана целиком.
Сильный ответ здесь такой: component test хорош там, где у объекта есть локальный пользовательский контракт. Если же риск рождается на стыке слоев, лучше честно подняться уровнем выше. Это тот же принцип, который подробно разбирается в статье про тестирование React компонентов через UI-контракты. Однако на интервью важно не сослаться на статью, а проговорить причину выбора самостоятельно.
2. Что в тестировании React реально меняет StrictMode, а что нет?
StrictMode в dev-среде повторно прогоняет некоторые жизненные циклы и эффекты, чтобы раньше вытащить неидемпотентную логику. Для тестов это важно не потому, что "рендерится два раза", а потому, что становятся видны лишние запросы, двойные подписки, неправильный cleanup и неконтролируемые побочные эффекты.
Плохой ответ звучит так: "Это только dev-особенность, в проде неважно". Хороший звучит иначе: dev-поведение само по себе не является production-багом, но оно подсвечивает сценарии, которые потом проявятся через повторный mount, race condition, retry, remount по key или изменение маршрута. Если нужен технический фон, его удобно связывать с материалом почему React рендерит дважды в dev-режиме.
3. Как тестировать debounced поиск так, чтобы не привязаться к таймингам?
Смысл теста не в том, чтобы проверить конкретные 300 ms, а в том, чтобы защитить бизнес-инвариант: пользователь вводит запрос, старый поиск не побеждает новый, UI остается отзывчивым, результаты соответствуют последнему вводу. Если тест завязан на магическое ожидание или ручные advanceTimersByTime без понимания модели, он легко становится хрупким.
Хорошая стратегия:
- проверить видимый переход состояний: ввод, loading, новые результаты;
- при необходимости использовать fake timers точечно, только если debounce действительно является частью контракта;
- отдельно защитить отмену старых запросов или игнорирование устаревшего ответа.
test("показывает результаты только для последнего запроса", async () => {
const user = userEvent.setup();
server.use(
http.get("/api/search", async ({ request }) => {
const url = new URL(request.url);
const q = url.searchParams.get("q");
if (q === "rea") {
await delay(200);
return HttpResponse.json([{ id: "1", title: "React old" }]);
}
return HttpResponse.json([{ id: "2", title: "React latest" }]);
})
);
render(<SearchBox />);
await user.type(screen.getByRole("searchbox", { name: /поиск/i }), "rea");
await user.clear(screen.getByRole("searchbox", { name: /поиск/i }));
await user.type(screen.getByRole("searchbox", { name: /поиск/i }), "react");
expect(await screen.findByText("React latest")).toBeInTheDocument();
expect(screen.queryByText("React old")).not.toBeInTheDocument();
});
4. Как тестировать optimistic update, чтобы сценарий был неполным без rollback?
Если тест проверяет только мгновенное обновление UI после клика, он закрывает ровно половину истории. Настоящий риск начинается в момент, когда сервер отвечает ошибкой, данные нужно откатить, а пользователь не должен остаться в ложном успешном состоянии.
Сильный ответ должен содержать полный цикл:
- локальное оптимистичное изменение;
- состояние pending;
- rollback при ошибке;
- финальную синхронизацию при успехе или refetch.
Это удобно связывать с практикой из React data/state: 17 сложных вопросов, где подробно разбираются ownership данных и invalidation после mutation.
5. Когда fake timers полезны, а когда они ломают доверие к тесту?
Fake timers полезны, когда время само является частью контракта: debounce, poll interval, auto-dismiss toast, delayed tooltip, retry backoff. Но если ими начинают подменять обычную асинхронность UI, тест перестает быть похожим на реальный сценарий и легко ломается рядом с user-event, промисами и внутренними таймерами библиотек.
Сильный ответ здесь не "я всегда избегаю fake timers", а "я использую их только там, где время является предметом проверки". Если проблема не во времени, а в переходах состояния, лучше тестировать переходы состояния.
6. Как правильно тестировать Suspense, чтобы не тестировать внутреннюю магию библиотеки?
Для Suspense обычно важны две вещи: пользователь видит корректный fallback и после завершения загрузки получает нужный экран без сломанного UX. Тест не должен проверять, что конкретная библиотека "дернула promise", он должен проверить контракт: был fallback, потом появился контент, а ошибка ушла в корректный boundary.
Если ответ строится на уровне "оберну в await screen.findByText", он поверхностный. Лучше проговорить границу:
- Suspense отвечает за временный UI при ожидании;
- error boundary отвечает за аварийный UI;
- query/data layer отвечает за источник асинхронности;
- тест должен проверять эти роли, а не реализацию кеша.
Это естественно дополняется статьями про паттерны data fetching в React и Suspense для данных, если тема на интервью идет глубже.
7. Что именно нужно проверить в модальном окне кроме самого факта открытия?
У модального окна риск редко ограничивается тем, что "оно появилось в DOM". По-настоящему важны focus trap, возврат фокуса после закрытия, реакция на Escape, блокировка фонового взаимодействия и правильная роль диалога. Именно здесь многие тесты недооценивают доступность.
Сильный ответ обычно перечисляет не div.modal, а пользовательский сценарий:
- фокус попадает внутрь модального окна;
- навигация табом не уходит в фон;
Escapeили кнопка закрытия закрывает модалку;- после закрытия фокус возвращается на исходный триггер.
8. Как тестировать accessibility у сложных виджетов, а не только у кнопок и инпутов?
На простых элементах getByRole уже многое дает. Но у Tabs, Combobox, Menu, Tree, Dialog и других composite widgets тест должен проверять отношения между ролями и управление с клавиатуры. Иначе получается ложное чувство безопасности: роль формально присутствует, но реальный сценарий сломан.
Сильный ответ звучит так: accessibility тестируется не отдельными атрибутами, а интерактивным контрактом. Для сложного виджета нужно проверить роль, name, selected/expanded/active descendant, видимую панель или опцию и keyboard flow. Это хорошо сочетается с базой из статьи React accessibility: a11y основы.
9. Когда integration-тест должен мокать сеть, а когда лучше идти в e2e?
Если задача проверить UI-сценарий на границе приложения: загрузка, ошибка, retry, пустое состояние, optimistic update, пагинация, фильтр, то integration-тест с мокированной сетью обычно дает лучший сигнал по цене. Если же риск живет в реальной браузерной среде, авторизации, cookie, storage, cross-page navigation или связке нескольких страниц, без e2e уже трудно.
Зрелый ответ не противопоставляет эти уровни, а раскладывает их по области риска. Это важнее, чем спор о том, использовать Playwright или любой другой инструмент. Базовый слой уже разобран в общем материале про React тестирование, но на интервью нужен именно критерий выбора.
10. Почему тест на React Query или другой cache layer легко становится ложноположительным?
Потому что happy path почти всегда выглядит красиво. Пользователь увидел список, нажал кнопку, UI обновился. Но без проверки устаревших данных, повторной загрузки, отката, инвалидации и повторного монтирования тест почти ничего не говорит о реальной надежности слоя данных.
Ложноположительный тест обычно имеет два признака:
- он проверяет только один успешный проход;
- он ничего не говорит о том, что произойдет после ошибки, повторного открытия экрана или фонового обновления данных.
11. Как тестировать URL-состояние фильтров без избыточного e2e?
Если фильтр, сортировка или активная вкладка являются shareable state, их необязательно тащить в браузерный e2e ради каждого кейса. В большинстве случаев достаточно integration-теста на уровень маршрута: стартуем с query-параметрами, убеждаемся, что экран восстановил нужное состояние, затем меняем фильтр и проверяем синхронизацию с URL.
Сильный ответ здесь показывает понимание ownership: URL нужен не ради красивого адреса, а ради восстанавливаемости и разделяемого состояния. Это логично связывать с темой из React data/state, где подробно разбирается граница между local state, URL и query cache.
12. Что плохого в тесте, который знает слишком много про renderWithProviders?
Как только тест начинает зависеть от скрытой магии общего helper-а, он становится труднее читать и хуже объясняет, какой контекст реально нужен сценарию. Это особенно заметно, когда один helper автоматически поднимает роутер, кэш, тему, auth, feature flags и еще половину окружения "на всякий случай".
Сильный ответ: helper нужен, чтобы убирать инфраструктурный шум, а не прятать смысл теста. Если без чтения внутренностей helper-а непонятно, в каком мире живет сценарий, слой уже стал слишком непрозрачным.
13. Как тестировать server error так, чтобы сценарий не заканчивался на сообщении об ошибке?
Потому что для пользователя ошибка почти никогда не является конечным состоянием. Обычно нужны recovery path: повтор запроса, возврат к редактированию, сохранение введенных данных, понятное сообщение и предсказуемое состояние кнопок.
Сильный ответ на интервью почти всегда включает это дополнение: тест ошибки должен защищать не только сам факт показа error UI, но и поведение интерфейса после него.
test("после ошибки сохранения пользователь может исправить данные и повторить попытку", async () => {
const user = userEvent.setup();
server.use(
http.post("/api/profile", () => new HttpResponse(null, { status: 500 }))
);
render(<ProfileForm />);
await user.type(screen.getByRole("textbox", { name: /имя/i }), "Anna");
await user.click(screen.getByRole("button", { name: /сохранить/i }));
expect(await screen.findByText(/не удалось сохранить/i)).toBeInTheDocument();
expect(screen.getByRole("textbox", { name: /имя/i })).toHaveValue("Anna");
server.use(
http.post("/api/profile", () => HttpResponse.json({ ok: true }))
);
await user.click(screen.getByRole("button", { name: /повторить/i }));
expect(await screen.findByText(/сохранено/i)).toBeInTheDocument();
});
14. Какой вопрос про mocks сразу отделяет зрелый тестовый подход от поверхностного?
Обычно это не "чем мокать fetch", а "на какой границе вы вообще мокируете систему". Если мокируются внутренние хуки, селекторы, адаптеры, функции форматирования и еще сетевой слой одновременно, тест почти неизбежно начинает защищать схему реализации, а не поведение.
Сильный ответ: внешние зависимости мокируются на границе системы, внутренние модули подменяются только когда без этого нельзя локализовать риск. Именно это делает MSW таким полезным приемом для integration-слоя: он держит мок на сетевой границе, а не вшивает тест в конкретную реализацию клиента.
15. Как проверить, что тест устойчив к безопасному рефакторингу?
Это один из самых полезных мета-вопросов. Если вы можете без изменения пользовательского контракта заменить useState на reducer, перенести логику в custom hook, поменять структуру wrapper-элементов, а тест при этом зеленый, значит он действительно привязан к поведению. Если же рефакторинг ломает тесты при неизменном UX, скорее всего они знали о реализации слишком много.
На интервью хорошо звучит простая эвристика: "сломается ли этот тест, если я перепишу компонент изнутри, но пользователь ничего не заметит?" Если ответ "да", тест подозрительный.
16. Как тестировать поведение после повторного mount, если баг проявляется только так?
Много production-багов не видны в одном прямолинейном сценарии. Они всплывают после ухода со страницы, повторного входа, смены key, повторного открытия модалки, refetch по фокусу окна или восстановлении вкладки. Поэтому иногда тест должен явно смоделировать размонтирование и новый mount, а не только один проход.
Это особенно важно для логики, где есть кэш, подписки, cleanup и синхронизация с внешним миром. Здесь сильный кандидат обычно связывает тему с эффектами, cleanup и реальной жизнью экрана, а не только с фактом "компонент показался".
17. Что интервьюер хочет услышать в вопросе про покрытие тестами, кроме слова coverage?
Coverage сам по себе не измеряет качество защиты. Он показывает только, какой процент кода был выполнен. Поэтому сильный ответ должен говорить не о цифре, а о распределении сигналов: какие пользовательские риски защищены, какие инварианты покрыты, где самые дорогие регрессии и какой слой ловит их быстрее всего.
Слабый ответ: "у нас было 85%". Сильный: "мы держали быстрый integration-слой на критичных экранах, немного e2e на дорогих путях и отдельно unit-тесты для правил, где ошибка дешева по коду, но дорога по бизнесу".
18. Как бы вы объяснили разницу между хорошим React-тестом и просто проходящим React-тестом?
Проходящий тест может просто совпасть с текущей реализацией. Хороший тест делает три вещи одновременно:
- ловит реальную регрессию, которую заметил бы пользователь или команда;
- переживает безопасный рефакторинг;
- падает понятным образом и подсказывает, что именно сломалось.
Это короткий, но очень сильный финальный ответ. Он показывает, что для вас тестирование не равно "заставить CI стать зеленым".
Код-пример: как проверять optimistic UI и rollback на integration-уровне
Ниже типичный сценарий, который часто недопокрывают. Тест должен показать не только локальное обновление, но и откат после ошибки.
test("откатывает оптимистическое изменение при ошибке сервера", async () => {
const user = userEvent.setup();
server.use(
http.get("/api/todos", () =>
HttpResponse.json([{ id: "1", title: "Write tests", completed: false }])
),
http.patch("/api/todos/1", () => new HttpResponse(null, { status: 500 }))
);
render(<TodosPage />);
const checkbox = await screen.findByRole("checkbox", { name: /write tests/i });
expect(checkbox).not.toBeChecked();
await user.click(checkbox);
expect(checkbox).toBeChecked();
expect(await screen.findByText(/не удалось обновить/i)).toBeInTheDocument();
expect(checkbox).not.toBeChecked();
});
Смысл примера в том, что тест защищает пользовательскую правду, а не внутренности query-клиента. Завтра можно поменять библиотеку данных, способ invalidation или структуру стора, а тест останется ценным, пока сценарий остается тем же.
Прокачай React за 7 дней
20 вопросов и разборов по React Hooks
Production pitfalls: где такие вопросы чаще всего ломают кандидатов
1. Кандидат отвечает инструментом вместо модели риска
Симптом:
- на любой вопрос звучит "я бы написал unit-тест" или "я бы взял Playwright";
- в ответе нет объяснения, что именно может сломаться;
- уровень теста выбирается по привычке, а не по цене ошибки.
Последствие в работе: тестовый слой растет хаотично, а дорогие регрессии продолжают пролетать мимо.
2. Асинхронность маскируют таймингами
Симптом:
- много
waitForбез понятной причины; - таймеры используются как универсальный костыль;
- тест проходит успешно только при удачном порядке событий.
Последствие: нестабильные (flaky) тесты в CI и ложное ощущение, что проблема "в инфраструктуре", хотя она в модели состояния.
3. Accessibility сводят к формальной проверке роли
Симптом:
- тест нашли элемент по роли и на этом остановились;
- не проверяется клавиатура, фокус и смена состояния сложного виджета;
- реально сломанный сценарий для keyboard user остается незамеченным.
Последствие: интерфейс проходит локальные проверки, но разваливается для части пользователей.
Разбор производительности тестового слоя
Быстрый тестовый слой важен не ради цифры в CI, а ради частоты обратной связи. Если integration-сценарии занимают слишком долго, команда начинает реже прогонять их локально, позже замечает регрессии и чаще идет в дорогие e2e там, где хватило бы уровня ниже.
Главные узкие места обычно такие:
- один тяжелый helper поднимает лишние провайдеры в каждом тесте;
- e2e дублируют то, что уже закрыто integration-слоем;
- сетевые мок-сценарии слишком шумные и плохо переиспользуются;
- часть флейков вынуждает делать перезапуски вместо исправления модели состояния.
Оптимизация оправдана, когда suite реально мешает разработке. Но если команда ускоряет тесты ценой выкидывания полезных интеграционных сценариев, это почти всегда ложная экономия.
Практики, которые делают ответы и тесты сильнее
- Начинайте ответ с риска: какой пользовательский или продуктовый дефект вы хотите поймать.
- Явно проговаривайте границу уровня теста: почему это component, integration или e2e.
- В асинхронных сценариях проверяйте не только успех, но и retry, rollback, cancelation или recovery.
- Для сложных виджетов тестируйте keyboard flow и focus management, а не только наличие роли.
- Держите моки на внешней границе системы и не подменяйте все внутренности сразу.
- Используйте code-пример как доказательство модели, а не как самоцель.
Как отвечать на интервью
Сильный ответ по React testing обычно занимает 30-60 секунд и строится по простой схеме:
- Сначала называете риск: что может сломаться для пользователя или продукта.
- Потом выбираете уровень теста и объясняете, почему именно он дает лучший сигнал.
- Дальше коротко описываете границу моков.
- В конце добавляете один edge case: ошибка, rollback, повторный mount, фокус, stale response.
Например, на вопрос про поиск с debounce хороший ответ может звучать так: "Я бы не проверял конкретные миллисекунды, а защитил бы сценарий последнего ввода. Если debounce является частью контракта, можно добавить fake timers, но главная проверка для меня в том, что устаревший ответ не перезаписывает новый результат и пользователь видит согласованный UI".
Потренируйте сложные React-вопросы в формате реального интервью
В Lexicon можно прогнать вопросы по тестированию React, получить обратную связь по глубине ответа и увидеть, где вы пока называете инструменты вместо инженерной модели
FAQ
Нужно ли на такие вопросы всегда отвечать через Jest или Vitest?
Нет. Инструмент вторичен. Если в ответе есть граница риска, уровень теста, модель моков и понимание асинхронности, вы уже звучите сильно. Название конкретного инструмента (раннера) без этого почти ничего не добавляет.
Стоит ли учить наизусть API Testing Library перед интервью?
Полезно помнить базовые приемы, но ценнее понимать, почему тест ищет элемент по роли, что считается пользовательским контрактом и как не превратить сценарий в проверку внутренних деталей.
Что чаще всего делает ответ слабым даже у опытного разработчика?
Поспешный переход к любимому инструменту без формулировки риска. Как только ответ начинается с "я бы просто..." и не объясняет why, глубина быстро теряется.
Нормально ли в ответе признавать trade-off и ограничения?
Да, и это обычно усиливает сигнал. Интервьюеру важнее услышать, где решение перестает быть выгодным, чем очередное универсальное правило без оговорок.
Если опыта с Suspense или optimistic update мало, как не провалиться?
Лучше честно обозначить границу опыта и рассуждать от инвариантов: какой временный UI видит пользователь, что происходит при ошибке, кто владеет данными и как избежать ложного успешного состояния. Такой ответ сильнее, чем уверенный, но поверхностный пересказ API.
Итоги
Сложные вопросы по React testing почти всегда упираются не в библиотеку, а в инженерную дисциплину: выбрать правильный уровень теста, не перепутать поведение и реализацию, учесть асинхронность, кэш, доступность и recovery path. Если вы умеете отвечать именно так, тема тестирования перестает выглядеть как набор разрозненных приемов и начинает звучать как зрелая модель разработки.
Для тренировки полезно не просто читать такие вопросы, а проговаривать ответ вслух: риск, уровень, мок, edge case. В этот момент очень быстро становится видно, где знание еще опирается на привычку, а где уже превратилось в системное мышление.
Больше вопросов в Telegram
Ежедневные разборы и реальные кейсы с интервью
Автор
Lexicon Team
Читайте также
frontend
Тестирование React компонентов: как проверять UI-контракты, состояния и доступность без хрупких тестов
Практический гид по тестированию React компонентов: что считать контрактом, как покрывать состояния, доступность и сложные виджеты без лишней хрупкости.
frontend
Jest + React Testing Library: как тестировать React без хрупких тестов
Практический разбор Jest и React Testing Library: архитектура тестов, async-сценарии, MSW, user-event, моки и ошибки, из-за которых тесты перестают ловить регрессии.
frontend
React тестирование: что нужно знать, чтобы писать полезные тесты
Разбираем React тестирование на практике: unit, integration, e2e, Testing Library, Vitest/Jest, частые ошибки, performance и ответы для собеседования.