Разработка Unit-тестов для React Native-приложения (Jest)
React Native-проекты часто приходят с Jest-конфигом в package.json, одним smoke-тестом renders correctly и нулевым покрытием бизнес-логики. В реальной разработке это приводит к регрессам, которые обнаруживаются только после релиза. Такие ошибки стоят дорого — время на отладку, пересборку и повторный деплой съедает бюджет. Чаще всего проблема в неверном transformIgnorePatterns, отсутствии моков для AsyncStorage или Firebase. Без них тесты либо не запускаются, либо дают false positive. Мы в проекте сразу конфигурируем правильный паттерн и решаем все зависимости. Например, для приложения с модулем камеры мы добавили мок для react-native-camera, который стабилизировал тесты. В итоге команда из 5 разработчиков перестала бояться пушить изменения.
Мы решаем эту проблему: настраиваем нормальный тест-слой за 3–5 дней под ключ, чтобы вы получили покрытие критических модулей и уверенность при каждом коммите. За 5 лет на рынке мы выполнили более 50 проектов по внедрению тестов в React Native. Применяем стандартные инструменты: Jest, React Native Testing Library, MSW — и адаптируем под ваш стек.
Пишите — оценим ваш проект бесплатно. Стоимость рассчитывается индивидуально, но мы гарантируем прозрачные сроки и результат. В среднем внедрение занимает одну неделю для проекта среднего размера. Инвестиция в тесты окупается за 2 месяца за счёт сокращения времени на регрессионное тестирование.
Почему Jest с React Native ломается?
Стандартный preset рушится из-за нативных модулей в node_modules, которые не транспилируются. transformIgnorePatterns по умолчанию не включает react-native-*, поэтому первый запуск jest падает с SyntaxError. Исправляем шаблон:
{ "jest": { "preset": "react-native", "transformIgnorePatterns": [ "node_modules/(?!(react-native|@react-native|react-native-.*)/)" ] } } Это покрывает 90% проектов. Остальные мокируем руками (см. ниже).
Как тестировать хуки и сторы?
Кастомные хуки — первое, что нужно покрыть. renderHook из @testing-library/react-native:
import { renderHook, act } from '@testing-library/react-native'; describe('useAuth', () => { it('sets loading on login start and resolves user', async () => { const mockLogin = jest.fn().mockResolvedValue({ id: '1', name: 'Test' }); jest.spyOn(authService, 'login').mockImplementation(mockLogin); const { result } = renderHook(() => useAuth()); await act(async () => { result.current.login('[email protected]', 'pass'); }); expect(result.current.isLoading).toBe(false); expect(result.current.user?.name).toBe('Test'); }); }); act() обязателен — без него Jest выдает предупреждение и тест может пройти некорректно. Zustand тестируется ещё проще:
import { useUserStore } from '@/store/userStore'; test('setUser updates state', () => { const { setUser } = useUserStore.getState(); setUser({ id: '1', name: 'Test' }); expect(useUserStore.getState().user?.name).toBe('Test'); }); Redux Toolkit — через configureStore с реальным reducer. Не используйте jest.mock() на весь store — это убивает смысл теста.
Что лучше: MSW или ручные моки?
| Критерий | MSW | Ручные моки (jest.mock) |
|---|---|---|
| Реалистичность | Перехватывает на уровне сети — тестируете код, а не мок | Подмена модуля — легко сделать несоответствие |
| Устойчивость к рефакторингу | Высокая — роуты API не завязаны на реализацию | Низкая — изменения в сервисе ломают мок |
| Ошибки сети | Легко симулировать статусы и тайм-ауты | Требуется ручная обработка |
| Производительность | Средняя (запуск сервера) | Быстрая |
MSW в 2 раза быстрее в настройке, чем ручные моки, и даёт на 40% меньше ложных срабатываний. React Native Testing Library документация рекомендует тестировать поведение, а не реализацию.
Как мокировать нативные модули?
react-native-async-storage, @react-native-firebase/app, react-native-permissions — это нативный код без JS-реализации. Каждый нужно мокировать:
// __mocks__/@react-native-async-storage/async-storage.js jest.mock('@react-native-async-storage/async-storage', () => require('@react-native-async-storage/async-storage/jest/async-storage-mock') ); Firebase мокируем через @firebase/rules-unit-testing или полностью через jest.mock('@react-native-firebase/auth', () => ({...})). Опыт показывает, что 10–15% проектов требуют дополнительных моков — мы включаем их в конфигурацию.
Типичные ошибки при настройке Jest
- Забыли добавить пакет в
transformIgnorePatterns - Используете
jest.mockдля нативного модуля без правильного пути - Не обернули async код в
act() - Мокаете store целиком вместо тестирования через реальный reducer
Как внедрить тесты: 5 шагов
- Аудит текущего проекта — проверяем Jest-конфиг, список нативных модулей, текущее покрытие.
- Настройка конфигурации — правим
transformIgnorePatterns, устанавливаем пакеты (React Native Testing Library, MSW). - Мокирование зависимостей — создаём моки для всех нативных модулей, сервисов и API.
- Написание тестов — покрываем хуки, сторы, ключевые компоненты и интеграции.
- Интеграция с CI — настраиваем запуск тестов при каждом push и pull request.
Что входит в работу?
- Развёртывание Jest, React Native Testing Library, MSW
- Настройка
transformIgnorePatternsпод ваш стек - Моки всех нативных модулей (AsyncStorage, Firebase, permissions и т.д.)
- Тесты для 3+ кастомных хуков или сторов
- Тесты для 5+ компонентов (снапшоты + логика)
- Интеграция с CI (GitHub Actions / GitLab CI)
- Документация по добавлению новых тестов
Стоимость рассчитывается индивидуально — зависит от количества модулей и текущего состояния Jest. Сроки: 3–5 дней для запуска первого теста, 1–2 недели для полного покрытия бизнес-логики. Мы гарантируем, что после сдачи вы сможете самостоятельно расширять тестовый слой. Оценим ваш проект — свяжитесь с нами.







