Mocking Bloc/Cubit In Flutter

Mario Gunawan
2 min readJan 4, 2023

It’s usually a best practice in unit/widget testing to mock outside dependencies when testing something so that when there’s an error relating to the dependencies, we can be sure that our test cases won’t be affected. Even if we developed it inside our app, Cubit still counts as a dependency in our widget. That’s why it is in our best interest to mock it.

Though, the process of mocking cubit is not as intuitive as you might have thought. So, here is how to mock cubits in flutter:

  1. Add those dependencies in your project
dependencies:
bloc:
flutter_bloc:

dev_dependencies:
mocktail:
flutter_test:
sdk: flutter

2. Create a cubit

# some_cubit.dart
import 'package:bloc/bloc.dart';

class CounterCubit extends Cubit<CounterState> {
CounterCubit() : super(const CounterState(0));
}

class CounterState {
final value;

const CounterState(this.value);
}

3. Create a stateless widget

# some_widget.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'some_cubit.dart';

class SomeWidget extends StatelessWidget {
const SomeWidget({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return BlocBuilder<CounterCubit, CounterState>(
builder: (context, state) => Text("${state.value}"),
);
}
}

4. Create the test

# some_widget_test.dart
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';

import 'some_cubit.dart';
import 'some_widget.dart';

// 1
class MockCounterCubit extends MockCubit<CounterState> implements CounterCubit {
}

// 2
class MockCounterState extends Fake implements CounterState {}

void main() {
group('SomeWidget', ()
late final CounterCubit counterCubit;

setUpAll(() {
// 3
registerFallbackValue(MockCounterState());

counterCubit = MockCounterCubit();
});

testWidgets("have the expected number", (tester) async {
// 4
when(() => counterCubit.state)
.thenAnswer((invocation) => const CounterState(1));

await tester.pumpWidget(
MaterialApp(
home: BlocProvider(
create: (_) => counterCubit,
child: const SomeWidget(),
),
),
);

expect(find.text("1"), findsOneWidget);
});
});
}

Explanations:

  1. We need to use MockCubit since it’s a listenable class. We can’t use the usual Mock here.
  2. This will be used in no. 3
  3. We have to register a fake state as fallback value. I suppose it’s for the initial value if bloc.state is empty, so that bloc doesn’t throw an error.
  4. Mock the cubit state!

If you want to add golden test, then add this dependency:

dev_dependencies:
golden_toolkit:

Then, add those test:

group('SomeWidget', () {
// ...

testGoldens("golden test some widget", (tester) async {
when(() => counterCubit.state)
.thenAnswer((invocation) => const CounterState(4));

await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(
child: BlocProvider(
create: (_) => counterCubit,
child: const SomeWidget(),
),
),
),
),
);

await multiScreenGolden(tester, "some_widget_golden");
});
}

Don’t forget to run fvm test --update-goldens before running golden test. You’re done! You can mock other functionalities as you’ve done before, and it’s no different from mocking other function.

--

--

Mario Gunawan

I'm a passionate mobile / web developer. Writing articles about software development, mainly about flutter and react.