Flutter使用Mockito模拟SharedPreferences调用setString报MissingStubError错误
问题原因
- Mockito在空安全模式下,默认要求所有非空返回值的方法必须提前配置桩(stub),哪怕你只需要验证方法调用、不需要关心返回值也需要配置
- 你之前的getString测试用例已经提前用
when给getString方法配置了桩,所以正常运行,但setString方法还没配置桩,所以调用时触发MissingStubError setString方法的返回值是Future<bool>,属于非空类型,没有匹配桩的时候就会抛出异常- 你当前测试用例的执行顺序是先调用
cacheLastNumberTrivia,此时就会触发setString执行,还没到verify步骤就会因为无桩抛出错误
解决方案
方案1:给setString方法提前配置桩(推荐)
在执行测试逻辑前,用when配置setString的返回值,不需要关心返回结果的话可以直接返回Future.value(true),修改测试用例如下:
test('should call sharedPreferences to cache the data', () { // 新增桩配置,any可匹配任意参数,也可替换为固定参数做精确匹配 when(mockSharedPreferences.setString(any, any)).thenAnswer((_) async => true); // 执行测试逻辑 dataSource.cacheLastNumberTrivia(tNumberTriviaModel); final expectedJsonString = jsonEncode(tNumberTriviaModel.toJson()); // 验证调用 verify(mockSharedPreferences.setString(cachedNumberTrivia, expectedJsonString)); });
如果配置桩后仍然报错,可检查传入的缓存key、序列化后的JSON字符串是否和实际调用的参数完全一致,优先用any匹配参数排查是否是参数匹配问题。
方案2:生成Mock类时开启returnNullOnMissingStub配置
如果不想每个方法都手动加桩,可以在生成Mock的注解中指定参数,修改模拟类生成配置:
@GenerateMocks([ SharedPreferences ], customMocks: [ MockSpec<SharedPreferences>(returnNullOnMissingStub: true) ])
修改后重新执行模拟类生成命令:flutter pub run build_runner build
该方案所有未配置桩的方法都会默认返回null,无需逐个加桩,缺点是在需要非空返回的场景可能隐藏空安全问题,适合简单测试场景使用。
方案3:全局配置Mockito默认桩行为
如果需要配置全局生效,可以在测试文件的main方法最开头添加配置:
void main() { // 全局开启缺省桩返回null,关闭缺省抛错逻辑 throwOnMissingStub = false; // 剩余测试代码 }
全局配置优先级低于单个Mock的returnNullOnMissingStub配置,也低于手动配置的when桩。
内容的提问来源于stack exchange,提问作者Naufal Rajabi
相关产品推荐
相关产品推荐

