Mocking callbacks in Dart/Flutter unit tests

This article is a guide on how to mock callback functions and verify that the callback functions are called in Dart/Flutter unit tests.
The article is divided into:
1. Introduction
Let's say we have a function readDate with the definition below:
void readData(void Function() onDataReadComplete) {
print('Reading data');
onDataReadComplete();
}
The function takes a callback onDataReadComplete as a lone positional parameter and it calls onDataReadComplete after it prints ('Reading data').
Our task here is to write a unit test to confirm that onDataReadComplete is run whenever readData runs.
In order to do this we need to mock onDataReadComplete and confirm that it is actually called.
2. Mocking The Callback
In other to mock the callback, we will use the mock library mockito.
The first step is to add the mockito dependecy to our project by including it in the pubspec.yaml file. We will also add the test library to the pubspec.yaml file.
dev_dependencies:
mockito:
test:
Mockito has two ways to generate mock objects:
For this article, we will use the manual mock implementation for simplicity.
A class can be mocked manually by creating a class that extends Mock and implements the class to be mocked.
Below is a sample from the documentation:
class MockHttpServer extends Mock implements HttpServer {}
This means we need a class to represent our function so our mock class can implement it.
We will make use of Dart's Callable Classes.
To allow an instance of your Dart class to be called like a function, implement the call() method.
This means we can represent our void Function() onDataReadComplete function as this below:
abstract class OnDataReadComplete {
void call();
}
The class is an abstract class since we won't be providing an implementation of the call method
.
The call method must have the same definition as the function to be mocked. This is why it is a void method.
Now, we can create our mock class like this below:
class MockOnDataReadComplete extends Mock implements OnDataReadComplete {}
We can now, use MockOnDataReadComplete in our test.
3. Testing The Callback
We will follow the following steps in testing the callback function:
- Create the mock object
mockOnDataReadCompleteusingMockOnDataReadComplete. - Run the
readDatafunction withmockOnDataReadCompletepassed as a parameter. - Use the
verifyfunction to confirm thatmockOnDataReadComplete()is called once. Note that you need to call the function like thismockOnDataReadComplete()and not just pass the variablemockOnDataReadCompleteto the verify function
test('onDataReadComplete gets called whenever readData runs', () {
//Creates the mock object
final mockOnDataReadComplete = MockOnDataReadComplete();
//Runs the function
readData(mockOnDataReadComplete);
//Confirm that the mock object is called
verify(mockOnDataReadComplete()).called(1);
});
Here is the full test file:
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
void readData(void Function() onDataReadComplete) {
print('Reading data');
onDataReadComplete();
}
abstract class OnDataReadComplete {
void call();
}
class MockOnDataReadComplete extends Mock implements OnDataReadComplete {}
void main() {
test('onDataReadComplete gets called whenever readData runs', () {
//Creates the mock object
final mockOnDataReadComplete = MockOnDataReadComplete();
//Runs the function
readData(mockOnDataReadComplete);
//Confirm that the mock object is called
verify(mockOnDataReadComplete()).called(1);
});
}
And now we run our tests and it passes!
The complete project can be found on Github.



