Dart Mockito 如何实现Mock对象可设置字段的存根与校验
Mockito Mock属性读写存根配置方案
问题复现
使用Mockito编写测试时遇到互斥问题:
- setUp阶段编写固定存根
when(mockStore.formType).thenReturn(const Edit())时,后续修改mockStore.formType取值永远返回固定的Edit()实例,测试断言失败 - 移除上述固定存根后,调用
mockStore.formType会直接抛出缺失存根错误
相关代码如下:
测试初始化代码:
group("VgnItmFormEvents", () { setUp(() { mockStore = MockManageVgnItmStore(); when(mockStore.formType).thenReturn(const Edit());// 若移除该行则会抛出缺失存根错误 })
失败的测试用例:
test('OnNameChanged', () async { mockStore.formType = Add(name: 'add'); expect(mockStore.formType, Add(name: 'add')); });
真实业务对象的字段实现:
// Store类中对应实现 FormType get formType => stateNotifiersVm.formType; set formType(FormType formType) => stateNotifiersVm.formTypeStateNotifier.setState(formType);
// stateNotifiersVm中对应实现 FormType get formType => _formType; set formType(FormType formType) => formTypeStateNotifier.setState(formType);
根因
Mockito默认生成的Mock类不会自动处理属性的setter逻辑,getter返回值完全由when声明的存根规则决定,写死固定返回值后,set操作不会对getter的返回结果产生任何影响。
解决方法
不要给getter写死固定返回值,在测试上下文中维护一个局部变量存储属性值,同时给getter、setter分别配置存根逻辑,模拟真实属性的读写行为:
group("VgnItmFormEvents", () { late MockManageVgnItmStore mockStore; setUp(() { mockStore = MockManageVgnItmStore(); // 初始化属性默认值,和原逻辑默认返回Edit()对齐 FormType currentFormType = const Edit(); // 存根getter:每次读取返回变量存储的最新值 when(mockStore.formType).thenAnswer((_) => currentFormType); // 存根setter:赋值时更新内部存储的变量值 when(() => mockStore.formType = any()).thenAnswer((invocation) { currentFormType = invocation.positionalArguments.first as FormType; }); }); test('OnNameChanged', () async { mockStore.formType = Add(name: 'add'); // 此时读取到的是赋值后的最新值,断言正常通过 expect(mockStore.formType, Add(name: 'add')); }); });
该配置同时解决两个问题:
- 初始阶段getter有合法存根,不会抛出缺失存根错误
- setter调用会同步更新内部存储的值,getter始终返回最新赋值结果,支持对赋值后的值做断言校验
内容的提问来源于stack exchange,提问作者BeniaminoBaggins
相关产品推荐
相关产品推荐

