Flutter单元测试报错:Binding尚未初始化(SharedPreference相关)
问题场景
在Flutter单元测试中调用包含SharedPreferences的函数时触发Binding has not yet been initialized错误,禁用SharedPreferences相关代码后测试可正常运行。
错误原因
SharedPreferences的实现依赖Flutter的ServicesBinding,而普通的test()函数不会自动初始化这个绑定,导致调用SharedPreferences.getInstance()时触发绑定未初始化的错误。
解决方案
方案1:初始化测试绑定(快速解决)
在测试文件的main()函数开头添加TestWidgetsFlutterBinding.ensureInitialized(),手动初始化测试所需的绑定:
修改后的User_test.dart代码:
import 'package:flutter_test/flutter_test.dart'; import 'package:unit_testf/user.dart'; void main() { // 初始化测试绑定,解决SharedPreferences依赖的绑定问题 TestWidgetsFlutterBinding.ensureInitialized(); test("a unit test", () async { User user = User("flutter"); final result = await user.userName(); expect(result, true); }); }
方案2:使用Mock隔离外部依赖(推荐,符合单元测试原则)
单元测试应聚焦被测类的逻辑,而非依赖真实的存储实现。通过mockito包模拟SharedPreferences,彻底隔离外部依赖:
- 添加依赖
在pubspec.yaml的dev_dependencies中添加:
dev_dependencies: flutter_test: sdk: flutter mockito: ^5.4.0 build_runner: ^2.4.4
- 生成Mock类
创建mock_shared_preferences.dart文件:
import 'package:mockito/mockito.dart'; import 'package:shared_preferences/shared_preferences.dart'; class MockSharedPreferences extends Mock implements SharedPreferences {}
运行命令生成mock代码:
flutter pub run build_runner build
- 修改被测类支持依赖注入
调整User.dart,允许传入SharedPreferences实例,方便测试时注入mock:
import 'package:shared_preferences/shared_preferences.dart'; class User { final String name; final SharedPreferences? prefs; User(this.name, {this.prefs}); Future<bool> userName() async { final prefsInstance = prefs ?? await SharedPreferences.getInstance(); await prefsInstance.setString("name", name); return true; } }
- 编写测试代码
import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:unit_testf/user.dart'; import 'package:unit_testf/mock_shared_preferences.dart'; void main() { test("a unit test", () async { final mockPrefs = MockSharedPreferences(); // 模拟setString方法返回true when(mockPrefs.setString("name", "flutter")).thenAnswer((_) async => true); User user = User("flutter", prefs: mockPrefs); final result = await user.userName(); expect(result, true); // 验证setString是否按预期被调用 verify(mockPrefs.setString("name", "flutter")).called(1); }); }
这种方式不仅解决了绑定问题,还能更精准地测试User类的逻辑,避免受平台环境影响,测试效率和稳定性更高。
内容的提问来源于stack exchange,提问作者Anand Suthar
相关产品推荐
相关产品推荐

