Mockito无法返回存根值,提示null不是Future<dynamic>子类型如何解决?
报错的根本原因是你调用的uploadImage方法参数和你设置存根时的参数不匹配,Mockito找不到对应存根就默认返回null,而uploadImage的返回类型是Future,因此抛出null is not a subtype of Future<dynamic>错误。
具体问题与修复方案
- 存根参数与实际调用参数不匹配
你设置存根时写的是when(imageSelector.uploadImage(null, 'folder')),但从测试代码里的verify逻辑可以看出,实际调用时第二个参数是'upload',第一个参数也不是null,参数完全不匹配导致存根没有生效。
修复建议:如果不需要校验参数的具体值,直接用Mockito的参数匹配器设置存根:
when(imageSelector.uploadImage(any(), any())) .thenAnswer((_) async => 'send this');
如果需要限制第二个参数为指定值,可以写为:
when(imageSelector.uploadImage(any(), 'upload')) .thenAnswer((_) async => 'send this');
测试初始化顺序错误
你在setUp中先调用了setupService(),这个方法会注册一个没有传logo参数的ImageSelectorMock实例,这个实例根本没有设置uploadImage的存根。即使后续测试代码里重新调用了带logo参数的getImageSelectorMock,如果你的ViewModel在初始化时提前读取了locator中的旧实例,也会拿到没有存根的对象触发报错。
修复建议:删掉setupService()中默认调用的getImageSelectorMock(),改为在测试用例里按需注册对应配置的mock实例。verify参数匹配问题
你当前verify的写法是verify(imageSelector.uploadImage('', 'upload')),如果实际调用时第一个参数不是空字符串,会导致verify失败。如果不需要校验第一个参数的具体值,可以改为:
verify(imageSelector.uploadImage(any(), 'upload'));
- 可选:简化异步存根写法
你用thenAnswer的时候已经加了async关键字,不需要额外嵌套Future.value,直接返回字符串即可,写法更简洁:
.thenAnswer((realInvocation) async => 'send this')
- 新版Mockito适配注意事项
如果你用的是支持空安全的5.x以上版本Mockito,手写class ImageSelectorMock extends Mock implements ImageSelector{}无法正常工作,需要用注解生成mock类:
import 'package:mockito/mockito.dart'; import 'package:mockito/annotations.dart'; @GenerateMocks([ImageSelector]) void main() {}
然后运行flutter pub run build_runner build生成对应的.mocks.dart文件,导入后使用生成的MockImageSelector类即可。
内容的提问来源于stack exchange,提问作者Ekama Emmanuel Uloho

