fluttercommunity / get_it

Get It - Simple direct Service Locator that allows to decouple the interface from a concrete implementation and to access the concrete implementation from everywhere in your App. Maintainer: @escamoteur
https://pub.dev/packages/get_it
MIT License
1.36k stars 149 forks source link

Problem when unregistering factory which has a subclass return type #371

Closed muzzah closed 1 month ago

muzzah commented 3 months ago

So Im trying to unit test some code. The code uses an extension method which mockito cannot mock. So what Ive tried to do is the following with the help of GetIt.

The method in question is googleSignIn.authenticatedClient which returns an AuthClient. So I have created a factory registration in my unit test

GetIt.instance.registerFactoryParam<AuthClient, GoogleSignIn, Null>((param1, param2) => authClient, instanceName: "authClient" );

and authClient here is a MockAuthClient object. The code being tested does the following

AuthClient client = DIService.get<AuthClient>(param1: _googleSignIn);

Now this all works well on the happy path. Thing is googleSign.authenticatedClient can return null but GetIt doesnt support null returns. I need to handle this situation in my code path so what I thought Id do is wrap this code in a try/catch and then try to have GetIt throw an exception (simulating a null return type problem that would occur at runtime if null was returned). To do this I do the following in my test case

await GetIt.instance.unregister(instanceName: "authClient");
GetIt.instance.registerFactoryParam<AuthClient, GoogleSignIn, Null>((param1, param2) => throw Error() );

Though I am getting the following error

dart:core                                               _AssertionError._throwNew
package:get_it/get_it_impl.dart 404:7                   _GetItImplementation._findFirstFactoryByNameAndTypeOrNull
package:get_it/get_it_impl.dart 433:9                   _GetItImplementation._findFactoryByNameAndType
package:get_it/get_it_impl.dart 1323:11                 _GetItImplementation.unregister
test/operations/user/account_provider_test.dart 254:30  main.<fn>.<fn>.<fn>

'package:get_it/get_it_impl.dart': Failed assertion: line 404 pos 7: 'type != null || const Object() is! T': GetIt: The compiler could not infer the type. You have to provide a type and optionally a name. Did you accidentally do `var sl=GetIt.instance();` instead of var sl=GetIt.instance;

If I change await GetIt.instance.unregister(instanceName: "authClient"); to await GetIt.instance.unregister(instance: authClient); in my unit test then the error changes slightly.

package:get_it/get_it_impl.dart 9:18                    throwIf
package:get_it/get_it_impl.dart 1417:5                  _GetItImplementation._findFactoryByInstance
package:get_it/get_it_impl.dart 1322:11                 _GetItImplementation.unregister
test/operations/user/account_provider_test.dart 254:30  main.<fn>.<fn>.<fn>

Bad state: This instance of the type MockAuthClient is not available in GetIt If you have registered it as LazySingleton, are you sure you have used it at least once?

If I set GetIt.instance.allowReassignment = true; then I dont need to worry about unregistering and all seems to work ok.

Not sure if this is a bug or just a constraint of the getIt library but thought Id check to see if I was doing something wrong.

escamoteur commented 3 months ago

you can't unregister just by using an instanceName, you have to provide the type that was used to register it. throwing an exception inside the factory function should be fine.

muzzah commented 3 months ago

im pretty sure I tried that as well and got a siimilar error message

escamoteur commented 3 months ago

Nope, that's just not possible because the error you got is that the registration could not be found. You have to use the same type you used when registering. You don't need an instanceName if you don't register more than one factory with that type. Am 27. Aug. 2024, 08:49 +0100 schrieb Mustafa @.***>:

im pretty sure I tried that as well and got a siimilar error message — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

escamoteur commented 2 months ago

did you solve this?