← ademola.dev / writing 7 min read
share →
FlutterUnit TestRiverpodClean Architecture

Implementing Unit Tests for Riverpod

Unit testing in Flutter helps identify bugs early and ensures code quality. This guide covers how to write clean, comprehensive unit tests for Riverpod state management using best practices and the right tooling. · Sun, Feb 12, 2023
Implementing Unit Tests for Riverpod

Unit testing in Flutter is a great way to ensure the quality of your code. It helps to identify bugs early on and reduce the risk of them making it to production. Unit tests can be written quickly and easily, and they provide a comprehensive overview of the code’s functionality.

Adding Dependencies

Add the following to pubspec.yaml:

dev_dependencies:
  flutter_test:
    sdk: flutter
  riverpod_test: ^latest_version
  mocktail: ^latest_version

Setting Up the Provider Container

Riverpod tests use ProviderContainer to scope providers without a widget tree:

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  late ProviderContainer container;

  setUp(() {
    container = ProviderContainer();
  });

  tearDown(() {
    container.dispose();
  });

  test('counter increments', () {
    expect(container.read(counterProvider), 0);
    container.read(counterProvider.notifier).increment();
    expect(container.read(counterProvider), 1);
  });
}

Testing AsyncNotifier

For async providers, use expectAsync or await with container.read:

test('fetches user data', () async {
  final container = ProviderContainer(
    overrides: [
      userRepositoryProvider.overrideWithValue(FakeUserRepository()),
    ],
  );

  final state = await container.read(userProvider.future);
  expect(state.name, 'Ademola');

  container.dispose();
});

Mocking Dependencies

Use mocktail to create fake implementations:

class FakeUserRepository extends Fake implements UserRepository {
  @override
  Future<User> getUser(String id) async {
    return User(id: id, name: 'Ademola');
  }
}

Best Practices

  • Always dispose the ProviderContainer in tearDown
  • Override dependencies at the container level, not inside providers
  • Test state transitions, not just final values
  • Use listenManual to track emissions over time

Unit tests for Riverpod are fast, isolated, and give you confidence that your state logic is correct before wiring it to the UI.

thoughts on this?

Hit reply — I read every email.

hello@demola.dev →
Next → Exploring gRPC and Flutter for Modern App Development