Розробка юніт-тестів для Flutter: BLoC, Riverpod, Mocktail

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

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

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

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

Чому варто інвестувати в юніт-тести для Flutter?

Юніт-тести скорочують час регресійного тестування на 30% і знижують кількість багів у продакшні вдвічі. Вони швидко виконуються (мілісекунди) і не потребують емулятора. Це перша лінія оборони при рефакторингу: якщо логіка зламалася, ви дізнаєтеся про це до збірки застосунку.

Стек для юніт-тестів

Інструмент Призначення Особливості
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 робить перевірку послідовності станів тривіальною:

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 запускаються миттєво.

Типові помилки при юніт-тестуванні Flutter

  • mocktail без registerFallbackValue для кастомних типів — any() не працює з нестандартними класами без реєстрації.
  • Тести, які мутують глобальний state — SharedPreferences або Hive у тестах потрібно ініціалізувати через SharedPreferences.setMockInitialValues({}) перед кожним тестом.
  • Відсутність tearDown — ProviderContainer.dispose() та StreamController.close() забувають, і тести течуть пам'яттю.
  • Занадто широкий охват: намагаються тестувати UI через юніт-тести замість 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.

Що входить у роботу

  • Написання юніт-тестів для бізнес-логіки, 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