Description
Hey guys!
I noticed an unexpected behavior in a project. Normally, we use ‘verify’ on mocked classes to verify the call.
If you use an unmocked class, you get an error message that it needs to be mocked.
So far so good.
Now I have noticed that if you call a method that injects a mocked class, e.g. via GetIt
, this error does not occur. Instead, ‘true’ is returned, which means that the test is valid. But the expected method call was not verified.
I got you guys, you all need a bit of code:
Code Example
Let's say we have a Repository and a Service:
import 'package:flutter/material.dart';
import 'package:injectable/injectable.dart';
import 'package:mockito_application_1/injectable/injectable.dart';
import 'package:mockito_application_1/test_repository.dart';
@lazySingleton
class TestService {
final TestRepository testRepository = getIt();
Future<void> doSthThenFetchIt({required String id}) async {
debugPrint('We are doing sth here');
testRepository.fetchSomething(id: id);
debugPrint('We fetched the stuff');
}
}
import 'package:flutter/material.dart';
import 'package:injectable/injectable.dart';
@lazySingleton
class TestRepository {
Future<void> fetchSomething({required String id}) async {
Future.delayed(Durations.medium4);
debugPrint('Ok ok ok ok ok, cool cococococooool');
}
}
And somewhere a Button will call the Service to doSthThenFetchIt
ElevatedButton(
onPressed: () {
getIt<TestService>().doSthThenFetchIt(
id: 'SomeId',
);
},
child: Text('TheFooButton'))
Now we want to test that when we tap the button. The call doSthThenFetchIt will be used:
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito_application_1/injectable/injectable.dart';
import 'package:mockito_application_1/main.dart';
import 'package:mockito_application_1/test_repository.dart';
import 'package:mockito_application_1/test_service.dart';
import 'mocks/mocks.mocks.dart';
void main() {
late TestService testService;
late MockTestRepository mockTestRepository;
setUp(() {
mockTestRepository = MockTestRepository();
getIt.registerSingleton<TestRepository>(mockTestRepository);
testService = TestService();
getIt.registerSingleton(testService);
getIt.allowReassignment = true;
});
testWidgets(
'verify tap on ElevatedButton will call TestService.doSthThenFetchIt with correct id',
(tester) async {
await tester.pumpWidget(const MyApp());
await tester.tap(find.byType(ElevatedButton));
verify(
testService.doSthThenFetchIt(id: 'SomeId'),
);
},
);
}
Now, this test is valid and will return true.
However, the call is not correct. Since I do not test whether the service is called correctly, but our verify now checks the repository.
If I now change the value of the Id and set it manually in the repository call, this is also correct.
Unfortunately, this makes the verify
invalid.