I am testing some Flutter/Dart code with an AsyncValue provider. I am using Andrea's example almost literally. My listener extends Mock but when I verify it the test fails with 'Used on a non-mockito object'.
Which non-mockito object is this talking about? My listener is a mock.
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:riverpod/riverpod.dart';
// a generic Listener class, used to keep track of when a provider
// notifies its listeners
class Listener<T> extends Mock {
void call(T? previous, T next);
}
void main() {
group('GeoData', () {
// This is a variation of Andrea's AuthController example minus the
// extra mock'ed AuthRepository dependency.
// https://codewithandrea.com/articles/unit-test-async-notifier-riverpod/
test('initialization with default GeoInfo data', () {
final container = ProviderContainer();
addTearDown(container.dispose);
final listener = Listener<AsyncValue<GeoInfo>>();
container.listen(geoDataProvider, listener, fireImmediately: true);
// ---> this is the line that fails the test with "Used on a non-mockito object"
verify(() => listener(null, const AsyncData<GeoInfo>(GeoInfo.empty())));
verifyNoMoreInteractions(listener);
});
});
}
'''
Yikes, I spent way too much time on this and went down more than one rabbit hole before I found it. This has nothing to do with initializing the mock wrongly and everything with the difference between mocktail and mockito 🤦♀️
The two packages are very similar but the syntax for the verify call is different.
Mocktail:
verify(() => listener(null, const AsyncData<GeoInfo>(GeoInfo.empty())));
Mockito:
verify(listener.call(null, const AsyncData<GeoInfo>(GeoInfo.empty()))).called(1);
Once I changed my call to the Mockito syntax the test passed as expected.