Flutter中如何Mock运行时创建的对象?
解决Flutter Widget测试中Mock数据库方法的问题
你现在的代码里saveData方法直接在内部实例化MyDatabase,这种硬编码的依赖关系导致没法用Mock替换真实的数据库实例。要解决这个问题,得先调整代码的依赖注入方式,再用mockito来Mock目标方法,具体步骤如下:
1. 重构代码,支持依赖注入
把MyDatabase的实例从saveData内部创建改为外部注入,最简单的方式是通过Widget的构造函数传入,不影响正常业务逻辑的同时,方便测试替换:
// 你的Widget类 class MyWidget extends StatefulWidget { // 新增数据库依赖参数,默认使用真实实例 final MyDatabase db; const MyWidget({super.key, MyDatabase? db}) : db = db ?? MyDatabase(); @override State<MyWidget> createState() => _MyWidgetState(); } class _MyWidgetState extends State<MyWidget> { void saveData(int number) async { // 不再自行创建db实例,使用Widget传入的对象 bool success = await widget.db.insert(number); // ...后续业务逻辑 } @override Widget build(BuildContext context) { return ElevatedButton( onPressed: () => saveData(123), child: const Text("Save Data"), ); } }
2. 用mockito生成Mock数据库类
首先在pubspec.yaml的开发依赖中添加mockito和build_runner:
dev_dependencies: flutter_test: sdk: flutter mockito: ^5.4.0 build_runner: ^2.4.4
创建一个mock类文件(比如mock_database.dart):
import 'package:mockito/mockito.dart'; import 'your_database_file_path.dart'; // 导入真实的MyDatabase类 class MockMyDatabase extends Mock implements MyDatabase {}
运行命令生成Mock相关代码:
flutter pub run build_runner build
3. 编写测试代码
在测试中创建Mock实例,设置预期行为,注入到Widget后验证方法调用:
import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'your_widget_file_path.dart'; import 'mock_database.dart'; void main() { testWidgets('测试按钮点击时调用Mock的insert方法', (tester) async { // 创建Mock数据库实例 final mockDb = MockMyDatabase(); // 设置预期:调用insert(123)时返回true when(mockDb.insert(123)).thenAnswer((_) async => true); // 将Mock实例注入Widget await tester.pumpWidget(MyWidget(db: mockDb)); // 模拟按钮点击 await tester.tap(find.text("Save Data")); await tester.pumpAndSettle(); // 等待异步操作完成 // 验证insert方法是否按预期被调用 verify(mockDb.insert(123)).called(1); }); }
补充说明
如果不想修改Widget构造函数,也可以用Provider、GetIt这类依赖注入框架管理MyDatabase实例,测试时替换成Mock对象即可——核心逻辑都是让依赖可以被外部替换,而非在方法内部硬创建。
内容的提问来源于stack exchange,提问作者Avdhoot Ubale
相关产品推荐
相关产品推荐

