如何在测试中重新向GetIt服务容器注册服务?
问题原因
你遇到的错误是因为GetIt的全局实例sl在第一个测试中已经注册了UserSettings单例,第二个测试重复调用registerSingleton时,GetIt不允许重复注册同一类型的单例,所以抛出了这个错误。另外你代码里还有个小问题:sl.registerSingleton<UserSettings>(u);中的u未定义,应该替换为settingsManager。
解决方法
方法1:每个测试后清理GetIt注册(推荐)
在测试结束后清除GetIt中的注册,确保每个测试都是独立的环境。可以用tearDown方法在每个测试执行完成后执行清理操作:
import 'package:test/test.dart'; import 'package:myapp/functional/injectionContainer.dart'; import 'package:myapp/functional/userSettings.dart'; import 'package:myapp/functional/api.dart'; void main() { // 每个测试结束后重置GetIt tearDown(() { sl.reset(); // 清除所有注册,也可以用sl.unregister<UserSettings>()只清除指定类型 }); test('Test api', () async { UserSettings settingsManager = UserSettings.usingMemory(); sl.registerSingleton<UserSettings>(settingsManager); Api api = Api(); // 测试逻辑 }); test('Test api 2', () async { UserSettings settingsManager = UserSettings.usingMemory(); sl.registerSingleton<UserSettings>(settingsManager); Api api = Api(); // 测试逻辑 }); }
方法2:允许覆盖已注册的实例
如果不想清理全局实例,可以在注册时添加overrideExisting: true参数,允许覆盖已有的单例注册:
sl.registerSingleton<UserSettings>(settingsManager, overrideExisting: true);
不过这种方法可能会残留上一个测试的状态,不如方法1的隔离性好,只适合简单场景。
方法3:使用独立的GetIt实例
为每个测试创建独立的GetIt实例,彻底隔离测试环境。这种方式需要调整你的依赖注入逻辑,让Api可以使用自定义的GetIt实例:
import 'package:test/test.dart'; import 'package:get_it/get_it.dart'; import 'package:myapp/functional/userSettings.dart'; import 'package:myapp/functional/api.dart'; void main() { test('Test api', () async { final getIt = GetIt.asNewInstance(); // 创建新的GetIt实例 UserSettings settingsManager = UserSettings.usingMemory(); getIt.registerSingleton<UserSettings>(settingsManager); // 假设Api可以接受GetIt参数,或者内部使用这个局部实例 Api api = Api(getIt: getIt); // 测试逻辑 }); test('Test api 2', () async { final getIt = GetIt.asNewInstance(); UserSettings settingsManager = UserSettings.usingMemory(); getIt.registerSingleton<UserSettings>(settingsManager); Api api = Api(getIt: getIt); // 测试逻辑 }); }
内容的提问来源于stack exchange,提问作者Dimitrios Desyllas
相关产品推荐
相关产品推荐

