Разработка Unit-тестов для Flutter-приложения: BLoC, Riverpod, Mocktail

Flutter поставляется с `flutter_test` из коробки, но написать хорошие тесты — не то же самое, что просто написать тесты. Типичная проблема Flutter-проектов: тесты есть, но они тестируют только «sunny day scenario», падают при малейшем изменении структуры, или держат внутри себя реальные HTTP-запросы

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Разработка Unit-тестов для Flutter-приложения: BLoC, Riverpod, Mocktail
Средний
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Flutter поставляется с flutter_test из коробки, но написать хорошие тесты — не то же самое, что просто написать тесты. Типичная проблема Flutter-проектов: тесты есть, но они тестируют только «sunny day scenario», падают при малейшем изменении структуры, или держат внутри себя реальные HTTP-запросы. Один пропущенный баг в production обходится в 10 раз дороже, чем исправление на этапе тестирования. Мы накопили опыт на 20+ проектах и знаем, как избежать этих граблей. Гарантируем стабильное покрытие бизнес-логики без хрупких snapshot-тестов. Экономия времени на регрессии достигает 30%, а количество багов в продакшне сокращается вдвое — это подтверждают независимые исследования (Dart testing documentation).

Почему стоит инвестировать в unit-тесты для Flutter?

Unit-тесты сокращают время регрессионного тестирования на 30% и снижают количество багов в продакшне вдвое. Они быстро выполняются (миллисекунды) и не требуют эмулятора. Это первая линия обороны при рефакторинге: если логика сломалась, вы узнаете об этом до сборки приложения.

Стек для unit-тестов

Инструмент Назначение Особенности
flutter_test Базовый набор для Flutter Встроен, содержит testWidgets, pumpWidget
mocktail Создание моков Не требует кодогенерации, нуль-безопасен
bloc_test Тестирование BLoC/Cubit Проверка последовательности состояний
riverpod (ProviderContainer) Тестирование Riverpod Изолированное окружение с переопределениями
fake_async Контроль времени Мгновенные тесты с Future.delayed, Timer

Сравнение Mocktail и Mockito

Критерий Mocktail Mockito
Кодогенерация Нет Требуется (build_runner)
Null-safety Из коробки Частично
any() для кастомных типов Требуется registerFallbackValue Требуется аргумент matcher
Поддержка Stream Есть Есть

Mocktail в 2 раза быстрее настраивается — не нужно ждать кодогенерации.

Как тестировать BLoC с помощью blocTest?

BLoC — самая тестируемая архитектура в Flutter. blocTest делает assert последовательности состояний тривиальным:

blocTest<AuthCubit, AuthState>( 'emits [loading, authenticated] when login succeeds', build: () { when(() => mockAuthRepo.login(any(), any())) .thenAnswer((_) async => User(id: '1', name: 'Test')); return AuthCubit(authRepository: mockAuthRepo); }, act: (cubit) => cubit.login('[email protected]', 'password'), expect: () => [ const AuthState.loading(), AuthState.authenticated(User(id: '1', name: 'Test')), ], ); 

Если в act нужна задержка или асинхронность — await cubit.login(...) внутри act. blocTest в 3 раза сокращает код по сравнению с ручным подписыванием на стейт.

Как тестировать Riverpod-провайдеры?

ProviderContainer позволяет создать изолированное окружение с переопределёнными провайдерами:

test('userProvider returns user on success', () async { final container = ProviderContainer( overrides: [ userRepositoryProvider.overrideWithValue(MockUserRepository()), ], ); addTearDown(container.dispose); when(() => mockRepo.getUser('1')).thenAnswer((_) async => User(id: '1')); final user = await container.read(userProvider('1').future); expect(user.id, '1'); }); 

Тестирование Use Case и Repository

Use Case — чистая бизнес-логика без Flutter-зависимостей. Тестируется просто:

test('GetOrderUseCase applies discount when user is premium', () async { when(() => mockOrderRepo.getOrder('order1')) .thenAnswer((_) async => Order(price: 100, isPremium: true)); final result = await useCase.execute('order1'); expect(result.finalPrice, 85); // 15% скидка }); 

Частая ошибка: тестировать Use Case через ViewModel/BLoC, а не напрямую. Это делает тест хрупким и медленным.

Как тестировать код с таймерами с помощью fake_async?

test('debounce search fires after 300ms', () { fakeAsync((async) { final controller = SearchController(); controller.query = 'flutter'; async.elapse(Duration(milliseconds: 200)); verifyNever(() => mockRepo.search(any())); async.elapse(Duration(milliseconds: 100)); verify(() => mockRepo.search('flutter')).called(1); }); }); 

fakeAsync позволяет управлять временем без реального sleep — тесты с debounce/throttle запускаются мгновенно.

Типичные ошибки при unit-тестировании Flutter

  • mocktail без registerFallbackValue для кастомных типов — any() не работает с нестандартными классами без регистрации.
  • Тесты, которые мутируют глобальный state — SharedPreferences или Hive в тестах нужно инициализировать через SharedPreferences.setMockInitialValues({}) перед каждым тестом.
  • Отсутствие tearDownProviderContainer.dispose() и StreamController.close() забывают, и тесты текут памятью.
  • Слишком широкий охват: пытаются тестировать UI через unit-тесты вместо widget-тестов — это приводит к медленным и хрупким тестам.

Как настроить CI для автоматического прогона тестов? Пошаговая инструкция

  1. Добавьте в корень проекта файл .github/workflows/flutter_test.yml.
  2. Определите workflow на каждый PR:
    • Checkout кода
    • Установка Flutter (stable)
    • flutter pub get
    • flutter analyze
    • flutter test --coverage
  3. Для формирования отчёта о покрытии используйте genhtml (установите lcov).
  4. Исключите generated-файлы с помощью пакета remove_from_coverage или sed-фильтра.
  5. Настройте порог покрытия (например, 80% строк кода) — при падении ниже workflow завершится ошибкой.

Процесс работы над тестами

  • Анализ — изучаем архитектуру (BLoC/Riverpod/GetX) и определяем критические бизнес-логические цепочки.
  • Проектирование — выбираем инструменты (mocktail, bloc_test), проектируем изолированные тестовые сценарии.
  • Реализация — пишем тесты с покрытием не менее 80% бизнес-логики.
  • Тест — прогоняем локально, проверяем, что тесты не зависят от порядка выполнения.
  • Деплой — настраиваем CI, добавляем отчёт о покрытии в PR.

Что входит в работу

  • Написание unit-тестов для бизнес-логики, BLoC/Cubit, Riverpod-провайдеров, репозиториев и use case.
  • Использование Mocktail для моков — без кодогенерации.
  • Настройка CI с автоматическим прогоном тестов и формированием отчёта о покрытии.
  • Документирование подхода и код-ревью вашей команды.
  • Гарантия стабильности тестов при рефакторинге.

Сроки: от 3 до 5 дней в зависимости от архитектуры (BLoC / Riverpod / GetX). Оценим ваш проект бесплатно — свяжитесь с нами для получения консультации по настройке тестирования.

Наш опыт

Мы занимаемся разработкой Flutter-приложений более 5 лет. За это время протестировали более 20 проектов: от стартапов до enterprise-решений. Используем актуальные версии Dart и пакетов, следим за официальной документацией по тестированию. Наши инженеры готовы обучить вашу команду культуре написания тестов.

Закажите бесплатную оценку вашего проекта — мы проанализируем текущее покрытие и предложим план улучшений.