Assertions in Dart and Flutter tests: mock invocations and parameters
This is the part of the ultimate cheat sheet dedicated to:
- testing invocations with
verify()
, - testing invocation parameters with
any()
.
In this series:
- expect and matcher
- equality matchers
- type and error matchers
- collection matchers
- numeric and comparable matchers
- universal and custom matchers
- matcher operators
- asynchronous expect and matchers
- Flutter widget matchers
- accessibility matchers
- golden matchers
- mock invocations and parameters
So far, we have used expect()
function to compare the results of some operations with the expected values. There is another category of checks developers constantly perform: ensuring that some side effect was triggered.
Verify invocations
For that, the verify()
function is used:
test('verify β', () {
final mock = MockService();
verify(() => mock.sideEffect(0));
});
This verify()
function comes from the mocktail package. The mockito package provides similar functionality.
For context, here is the definition of MockService
:
abstract class Service {
void sideEffect(int value, {Result? result});
}
class MockService extends Mock implements Service {}
The verify()
function ensures that provided method was called at least once. The test above fails because the sideEffect()
method was never called, with the following output:
No matching calls (actually, no calls at all).
To ensure certain method was called exactly N times, use the called()
method of verify()
function result:
test('verify β', () {
final mock = MockService();
verify(() => mock.sideEffect(0)).called(1);
});
To ensure certain method was never called, use the verifyNever()
function:
test('verifyNever β
', () {
final mock = MockService();
verifyNever(() => mock.sideEffect(0));
});
Verify parameters
In the example above, the sideEffect()
method accepts two parameters. In case their values do not matter, use the any()
object that can represent literally any value:
test('verify: any β
', () {
final mock = MockService()..sideEffect(0, result: Result(0));
verify(() => mock.sideEffect(any(), result: any(named: 'result')));
});
In case invocation parameters matter, real values can be used instead of any()
:
test('verify: any β
', () {
final mock = MockService()..sideEffect(0, result: Result(0));
verify(() => mock.sideEffect(0, result: Result(0)));
});
Similar to equals
matcher, verify
will compare parameters using the equality operator. Thus, for the above test to pass, the Result
class has to have the operator ==
overridden, as was shown before. Otherwise, the test fails with the following output:
No matching calls.
All calls: MockService.sideEffect(0, {result: Result{value: 0}})
In case you are only interested in checking those parameters met some condition, any()
call can accept one of the matchers we looked so closely at before as that
parameter:
test('verify: any that β
', () {
final mock = MockService()..sideEffect(0, result: Result(0));
verify(() => mock.sideEffect(
any(that: isZero),
result: any(named: 'result', that: allOf(isResult, hasValue(0))),
));
});
Originally published at Invertase blog. Check out their awesome Authors Program!
Hi! ππ» Iβm Anna, Google Developer Expert in Flutter from Ukraine πΊπ¦ Follow me on Twitter, GitHub, YouTube, Medium to get notifications about my latest work.
Itβs early 2023, and we in Ukraine are still fighting against russians committing genocide on our lands. If you find this content useful and have a coin to spare, support us with your donations. Stand with Ukraine!