BLoC Testing with Mockito in Flutter

When working with Flutter and BLoC for state management, it’s crucial to write robust tests to ensure your app behaves correctly. In this blog, we’ll walk through testing a Flutter BLoC using Mockito, focusing on a repository pattern.

Steps Covered:

  1. Define an abstract repository (ChallanRepo)

  2. Implement the repository (ChallanRepoImpl)

  3. Create a BLoC (ChallanBloc) to fetch a list of challans

  4. Write unit tests using Mockito for the BLoC’s behavior

1️⃣ Define the Abstract Repository

We start by creating an abstract class ChallanRepo, which declares the getChallanList() method.

abstract class ChallanRepo {
  Future<List<String>> getChallanList();
}

2️⃣ Implement the Repository (ChallanRepoImpl)

This class simulates an API call by returning a hardcoded list after a delay.

class ChallanRepoImpl implements ChallanRepo {
  @override
  Future<List<String>> getChallanList() async {
    await Future.delayed(Duration(seconds: 1));
    return ["Challan 101", "Challan 102", "Challan 103"];
  }
}

3️⃣ Create the BLoC (ChallanBloc)

The BLoC manages states and events related to fetching challan data.

📌 Events

abstract class ChallanEvent {}
class GetChallanEvent extends ChallanEvent {}

📌 States

abstract class ChallanState {}
class ChallanListLoadingState extends ChallanState {}
class ChallanListEmptyState extends ChallanState {}
class ChallanListLoadedState extends ChallanState {
  final List<String> challanList;
  ChallanListLoadedState(this.challanList);
}
class ChallanListErrorState extends ChallanState {
  final String message;
  ChallanListErrorState(this.message);
}

📌 BLoC Implementation

import 'package:flutter_bloc/flutter_bloc.dart';
class ChallanBloc extends Bloc<ChallanEvent, ChallanState> {
  final ChallanRepo challanRepo;
ChallanBloc(this.challanRepo) : super(ChallanListLoadingState()) {
    on<GetChallanEvent>(_onGetChallanList);
  }
Future<void> _onGetChallanList(
      GetChallanEvent event, Emitter<ChallanState> emit) async {
    try {
      emit(ChallanListLoadingState());
      final challanList = await challanRepo.getChallanList();
      if (challanList.isEmpty) {
        emit(ChallanListEmptyState());
      } else {
        emit(ChallanListLoadedState(challanList));
      }
    } catch (e) {
      emit(ChallanListErrorState("Failed to fetch challans"));
    }
  }
}

4️⃣ Writing Tests with Mockito

📌 Install Dependencies

Add the necessary dependencies to pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: <take latest version>
  mockito: <take latest version>
dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: <take latest version>
  build_runner: <take latest version>
  bloc_test: <take latest version>

Run:

flutter pub get

📌 Step 2: Generate Mock Class

Create a test file: test/challan_bloc_test.dart and add:

import 'package:mockito/annotations.dart';
import '../lib/challan_repo.dart';
@GenerateMocks([ChallanRepo])
void main() {}

Generate the mock class by running:

flutter pub run build_runner build

This creates test/challan_bloc_test.mocks.dart.

📌 Step 3: Write the Test

Create test/challan_bloc_test.dart and add the following:

import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
import 'package:bloc_test/bloc_test.dart';
import '../lib/challan_repo.dart';
import '../lib/challan_bloc.dart';
import 'challan_bloc_test.mocks.dart';
@GenerateMocks([ChallanRepo])
void main() {
  late ChallanBloc challanBloc;
  late MockChallanRepo mockChallanRepo;
  setUp(() {
    mockChallanRepo = MockChallanRepo();
    challanBloc = ChallanBloc(mockChallanRepo);
  });
  tearDown(() {
    challanBloc.close();
  });
  test("Initial state should be ChallanListLoadingState", () {
    expect(challanBloc.state, isA<ChallanListLoadingState>());
  });
  blocTest<ChallanBloc, ChallanState>(
    "Should emit [ChallanListLoadingState, ChallanListLoadedState] when fetching challans successfully",
    build: () {
      when(mockChallanRepo.getChallanList()).thenAnswer(
          (_) async => ["Challan 101", "Challan 102", "Challan 103"]);
      return challanBloc;
    },
    act: (bloc) => bloc.add(GetChallanEvent()),
    expect: () => [
      ChallanListLoadingState(),
      ChallanListLoadedState(["Challan 101", "Challan 102", "Challan 103"]),
    ],
  );
  blocTest<ChallanBloc, ChallanState>(
    "Should emit [ChallanListLoadingState, ChallanListEmptyState] when API returns an empty list",
    build: () {
      when(mockChallanRepo.getChallanList()).thenAnswer((_) async => []);
      return challanBloc;
    },
    act: (bloc) => bloc.add(GetChallanEvent()),
    expect: () => [ChallanListLoadingState(), ChallanListEmptyState()],
  );
  blocTest<ChallanBloc, ChallanState>(
    "Should emit [ChallanListLoadingState, ChallanListErrorState] when API throws an error",
    build: () {
      when(mockChallanRepo.getChallanList()).thenThrow(Exception("API error"));
      return challanBloc;
    },
    act: (bloc) => bloc.add(GetChallanEvent()),
    expect: () => [ChallanListLoadingState(), ChallanListErrorState("Failed to fetch challans")],
  );
}
🔥 Recap

✔ Created ChallanRepo (abstract class) and ChallanRepoImpl (implementation).
✔ Implemented ChallanBloc with GetChallanEvent and state management.
✔ Used Mockito to test the BLoC’s behavior.
✔ Tested success, empty, and error cases using bloc_test.

By following this structured approach, you can ensure your Flutter BLoC is well-tested and functions correctly in different scenarios. Happy coding! 🚀

0
Subscribe to my newsletter

Read articles from NonStop io Technologies directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

NonStop io Technologies
NonStop io Technologies

Product Development as an Expertise Since 2015 Founded in August 2015, we are a USA-based Bespoke Engineering Studio providing Product Development as an Expertise. With 80+ satisfied clients worldwide, we serve startups and enterprises across San Francisco, Seattle, New York, London, Pune, Bangalore, Tokyo and other prominent technology hubs.