如何对ViewModel中调用Provider的方法进行单元测试
你提供的示例代码末尾存在多余的闭合符号});,测试前需要先修复该语法问题。针对你的问题,有两种可选方案,不需要强制重构。
方案1:不重构直接测试
直接测试是完全可行的,只需要在测试用例中模拟好依赖的Context和Provider实例即可,步骤如下:
- 引入
mockito框架编写PersonProvider的模拟实现,提前预设user.id的返回值 - 在测试用例中构造带Provider注入的上下文,将模拟的
PersonProvider实例提前挂载到组件树中 - 拿到构造好的上下文传入
onSubmit方法执行,验证返回值和isLoading状态即可
示例测试代码:
import 'package:mockito/mockito.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:provider/provider.dart'; // 模拟PersonProvider class MockPersonProvider extends Mock implements PersonProvider { @override User get user => MockUser(); // 同样模拟User类,预设id返回值 } class MockUser extends Mock implements User { @override String get id => 'test_user_id'; } test('test onSubmit', () async { final mockProvider = MockPersonProvider(); late BuildContext testContext; // 构造带Provider的测试组件 await tester.pumpWidget( MultiProvider( providers: [ ChangeNotifierProvider<PersonProvider>.value(value: mockProvider), ], child: Builder( builder: (context) { testContext = context; return Container(); }, ), ), ); // 调用待测方法 final result = await yourViewModel.onSubmit(testContext); // 验证结果 expect(result, 'hello'); expect(yourViewModel.isLoading, true); });
方案2:重构后测试(更推荐)
直接测试需要额外构造上下文和模拟组件树,测试成本更高,建议做轻量重构:将依赖的Provider直接注入到ViewModel中,不需要通过BuildContext获取,重构后的函数示例:
// ViewModel构造时就传入依赖的PersonProvider class YourViewModel { final PersonProvider personProvider; YourViewModel(this.personProvider); bool isLoading = false; Future<String> onSubmit() async { String userId = personProvider.user.id; isLoading = true; return 'hello'; } }
重构后测试不需要构造上下文,直接传入模拟的PersonProvider即可:
test('test onSubmit after refactor', () async { final mockProvider = MockPersonProvider(); final viewModel = YourViewModel(mockProvider); final result = await viewModel.onSubmit(); expect(result, 'hello'); expect(viewModel.isLoading, true); });
内容的提问来源于stack exchange,提问作者Emmanuel Okocha
相关产品推荐
相关产品推荐

