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

Ваши unit-тесты для Flutter часто падают при малейших изменениях или зависят от реальных запросов? Мы разрабатываем надёжные тесты для BLoC, Riverpod и Mocktail, которые проверяют именно бизнес-логику, а не хрупкие детали реализации. Наша команда реализует проект под ключ — от аудита текущего покрытия до внедрения и последующей поддержки, чтобы вы были уверены в стабильности кода.

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

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

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

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

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({}) перед каждым тестом.
  • Отсутствие tearDown — ProviderContainer.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 и пакетов, следим за официальной документацией по тестированию. Наши инженеры готовы обучить вашу команду культуре написания тестов.

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

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

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

  • Разработка мобильного приложения для компании FEEDME
    Разработка мобильного приложения для компании FEEDME
    1009
  • Разработка мобильного приложения для компании XOOMER
    Разработка мобильного приложения для компании XOOMER
    902
  • Разработка мобильного приложения для компании RHL
    Разработка мобильного приложения для компании RHL
    1331
  • Разработка мобильного приложения для компании ZIPPY
    Разработка мобильного приложения для компании ZIPPY
    1179
  • Разработка мобильного приложения для компании Affhome
    Разработка мобильного приложения для компании Affhome
    1106
  • Разработка мобильного приложения для компании FLAVORS
    Разработка мобильного приложения для компании FLAVORS
    713