Introduction
Unit testing is a critical part of building robust Flutter applications, especially when you’re using Bloc Cubits for state management. By isolating your business logic in Cubits and mocking external dependencies with Mockito, you can verify state transitions reliably and quickly. In this tutorial, you’ll learn how to set up Mockito for Flutter bloc testing, create a simple Cubit with a repository, and write unit tests (including bloc_test integration) to cover successful and failure scenarios.
Setting Up Dependencies for Flutter bloc testing
First, add the necessary dev dependencies to your pubspec.yaml:
dev_dependencies:
flutter_test:
sdk: flutter
bloc_test: ^9.0.0
mockito: ^5.0.0
build_runner
Run flutter pub get.
Create a file test/mocks.dart and annotate your external dependencies:
import 'package:mockito/annotations.dart';
import 'package:your_app/data/counter_repository.dart';
@GenerateMocks([CounterRepository])
void main() {}Run flutter pub run build_runner build to generate mocks.mocks.dart.
This setup gives you MockCounterRepository to inject controlled responses in unit tests.
Building a Sample Cubit and Repository
Let’s define a simple repository interface and a Cubit that relies on it. The Cubit will emit a new integer each time increment() is called:
abstract class CounterRepository {
Future<int> fetchNextCount(int current);
}
import 'package:bloc/bloc.dart';
import '../data/counter_repository.dart';
class CounterCubit extends Cubit<int> {
final CounterRepository repository;
CounterCubit(this.repository) : super(0);
Future<void> increment() async {
final next = await repository.fetchNextCount(state);
emit(next);
}
}Here, CounterCubit starts at 0 and invokes repository.fetchNextCount(state) in increment(), then emits the new state.
Writing Unit Tests with Mockito
With your mocks generated, you can now write tests that verify state emissions based on mocked repository behavior. Create test/counter_cubit_test.dart:
import 'package:flutter_test/flutter_test.dart';
import 'package:bloc_test/bloc_test.dart';
import 'package:mockito/mockito.dart';
import 'package:your_app/cubit/counter_cubit.dart';
import 'package:your_app/data/counter_repository.dart';
import 'mocks.mocks.dart';
void main() {
late MockCounterRepository mockRepo;
setUp(() {
mockRepo = MockCounterRepository();
});
test('increment emits [1] when repository returns 1', () async {
when(mockRepo.fetchNextCount(0))
.thenAnswer((_) async => 1);
final cubit = CounterCubit(mockRepo);
expectLater(cubit.stream, emitsInOrder([1]));
await cubit.increment();
});
blocTest<CounterCubit, int>(
'emits [1, 2] on two increments with bloc_test',
build: () => CounterCubit(mockRepo),
act: (cubit) async {
when(mockRepo.fetchNextCount(0))
.thenAnswer((_) async => 1);
when(mockRepo.fetchNextCount(1))
.thenAnswer((_) async => 2);
await cubit.increment();
await cubit.increment();
},
expect: () => [1, 2],
);
}Explanation:
We mock fetchNextCount for specific input states (0 and 1).
The first test uses expectLater to observe one state emission.
The second leverages bloc_test’s blocTest for a clean, declarative style. It asserts the Cubit emits [1, 2] after two increment() calls.
Leveraging bloc_test for Enhanced Flutter bloc testing
bloc_test provides utilities to:
• Isolate builds with the build callback.
• Sequence multiple actions under act.
• Declaratively assert emissions in expect.
• Handle error states with errors param.
You can further test edge cases by mocking exceptions:
when(mockRepo.fetchNextCount(any))
.thenThrow(Exception('Network error'));
blocTest<CounterCubit, int>(
'emits error when repository throws',
build: () => CounterCubit(mockRepo),
act: (c) => cubit.increment(),
errors: () => [isA<Exception>()],
);This pattern ensures your Bloc Cubit gracefully surfaces exceptions as testable events.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
Unit testing Bloc Cubits with Mockito and bloc_test unlocks faster, more reliable Flutter bloc testing. By mocking your repositories, you decouple network or database logic from Cubit behavior, ensuring pure state-transition tests. Incorporate this workflow into your CI pipeline to catch regressions early and boost confidence in your business logic.