I'm currently writing unit tests for a Flutter app using mockito
, and I'm running into an issue with verifying a getter call using the latest version of mockito
(v5.x).
Here's my test setup:
@GenerateMocks([InternetConnectionChecker])
void main() {
late MockInternetConnectionChecker internetConnectionChecker;
late NetworkInfoImpl networkInfo;
setUp(() {
internetConnectionChecker = MockInternetConnectionChecker();
networkInfo = NetworkInfoImpl(internetConnectionChecker);
});
test('should check internet connection', () async {
// Arrange
when(() => internetConnectionChecker.hasConnection)
.thenAnswer((_) async => true);
// Act
final result = await networkInfo.isConnect;
// Assert
verify(() => internetConnectionChecker.hasConnection); // ❌ Throws error
expect(result, true);
});
}
Even though internetConnectionChecker
is clearly a MockInternetConnectionChecker
, the test throws this error:
Used on a non-mockito object
package:matcher fail
package:mockito/src/mock.dart 1155:7 _makeVerify.<fn>
test\core\network\network_info_test.dart 30:13 main.<fn>.<fn>
However, if I write it like this, it works:
verify(internetConnectionChecker.hasConnection); // ✅ Works, but discouraged?
From what I understand, using verify(() => ...) is the recommended way to ensure that the method or getter was actually called. So why does this error happen?
Ran flutter pub run build_runner build --delete-conflicting-outputs
Verified that the correct imports are used: package:mockito/mockito.dart
Confirmed the type via print(internetConnectionChecker.runtimeType)
→ MockInternetConnectionChecker
Is there something special about getters in the latest versions of mockito
? Or has there been a breaking change that I missed?
when
requires a method call to be recorded on a Mockito mock instance. Same goes for verify
.
When you write when(() => internetConnectionChecker.hasConnection)
or verify(() => internetConnectionChecker.hasConnection)
, you are not calling a method. You are passing a lambda instead.
A lambda is not a mock (it's a lambda. yourMock
is a mock, but () => yourMock
is not a mock. yourMock.method()
calls a method on your mock, () => yourMock.method()
does not call the method on your mock. It wraps it in a lambda to be invoked at a later point in time).
Passing a lambda will not invoke the lambda and consequently not call the method on your mock.
Check the Flutter docs for example how to set up your mocks with when
:
when(
client.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1')),
).thenAnswer((_) async => http.Response('Not Found', 404));
or how to verify
the calls on your mocks:
cat.eatFood("chicken");
verify(cat.eatFood("fish"));