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 147 forks source link

how to use get_it in integration test #106

Closed PandaGeek1024 closed 3 years ago

PandaGeek1024 commented 4 years ago

Im new to flutter integration testing so Im quite confused of how to provide mock data for integration test.

I have followed the official doc to create app.dart

void main() async{
  enableFlutterDriverExtension();
  app.main();
}

but because i have put my getit setup in app main.dart

void main() async {
  await Firebase.initializeApp();
  setupGetItLocator();
  runApp(MyApp());
}

So that means I cannot use app.main()

I do have seen people said we can use runApp() and do something like

void main() {
  enableFlutterDriverExtension();
  GetIt locator = GetIt.instance;
  locator.registerFactory<Parent>(() => Child("jason"));
  runApp(MyApp());
}

but the problem is I have got some configuration setup in the app main() as well. main.dart

void main() async {
  await Firebase.initializeApp(); //need this
  setupGitItLocator();
  runApp(MyApp());
}

How do I keep the integration test with the same setup except for mock data.

Or a more sensible question, what is the best practice for integration test? Can you provide an example please. Thanks

escamoteur commented 4 years ago

Can you describe, what's an integration test for you? what do you want to mock? In the above example you register a factory. When you want to mock objects inside GetIt, you typically register an abstract parent class and use that to access the object with GetIt. In the registration you can then replace the real object with a mock object. Check the readme on this too

PandaGeek1024 commented 4 years ago

Integration test is to test the flow of the app. I have created a bunch of abstract classes and want to provide mock implementation for the integration test.

Yes, I did see that example in readme.

  if (testing) {
    getIt.registerSingleton<AppModel>(AppModelMock());
  } else {
    getIt.registerSingleton<AppModel>(AppModelImplementation());
  }

But how do I provide this testing variable from my integration test? This is the app test main file that copied from the official doc

void main() async{
  enableFlutterDriverExtension();
  // Call the `main()` function of the app
  app.main(); // the actual main function does not have a parameters to pass in
}
escamoteur commented 4 years ago

What about this approach? https://itnext.io/flutter-1-17-no-more-flavors-no-more-ios-schemas-command-argument-that-solves-everything-8b145ed4285d

PandaGeek1024 commented 4 years ago

That looks like a way, but is this the only way? are you able to provide a proper way in the README, that should be a big help for those (including me) who are looking for a solution.

escamoteur commented 4 years ago

The question is what is a proper way. it's actually outside the scope of get_it how you provide config values into your app. The way above is nice for CI systems because you can pass them on the command line.

PandaGeek1024 commented 4 years ago

Maybe that's not a question for here, but would flutter team comes up with something like the android-dagger doc that provides a full solution from development to testing. I think that's what everyone would like to see.