flutterdependency-injectionintegration-testingtestcasewidget-test-flutter

Flutter Integration testing failed for multiple test cases in a single file


I have a simple login page with email and password text field. A button to login and another to sign up. I tried to write integration testing for the Sign in page.

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('''could type email and password in text filed''',
      (WidgetTester tester) async {
    await app.main();
    await tester.pumpAndSettle();

    final textFieldEmail = find.byType(InputTextWidget).first;
    final textFieldPassword = find.byType(InputTextWidget).last;

    await tester.enterText(textFieldEmail, "asis.adh@gmail.com");
    await tester.pumpAndSettle();

    expect(find.text("asis.adh@gmail.com"), findsOneWidget);
  });

testWidgets(
      'should redirect to Sign Up Page when create an account is tapped',
      (WidgetTester tester) async {
    await app.main();
    await tester.pumpAndSettle();

    final createAnAccount = find.text("Create an account");
    await tester.tap(createAnAccount);

    await tester.pumpAndSettle();

    expect(find.byType(SignupPage), findsOneWidget);
    expect(find.byType(LoginPage), findsNothing);
  });
}

When I execute the test case, it fails with the following error:

The following ArgumentError was thrown running a test: Invalid argument(s): Object/factory with type AmenitiesProvider is already registered inside GetIt.

Here is my main.dart file

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  configureInjection(Environment.prod);

  /// for registering the factory.
  await Future.delayed(const Duration(seconds: 2));
  runApp(RoopaApp());
}

I tried with a main_test.dart and adding configureInjection(Environment.test) but nothing changes. I am not sure how to fix the error. Is there a way to clean the app or destroy it before going to new test case. If I combine the both testcase into one then it works without any problem.

Here is configureInjection

@injectableInit
void configureInjection(String environment) {
  $initGetIt(getIt, environment: environment);
}

I am using get_it and injection package for dependency injection.

Here is the auto generated initGetIt

GetIt $initGetIt(
  GetIt get, {
  String environment,
  EnvironmentFilter environmentFilter,
}) {
  final gh = GetItHelper(get, environment, environmentFilter);
  final httpClientInjectableModule = _$HttpClientInjectableModule();
  final flutterStorageModule = _$FlutterStorageModule();
  gh.lazySingleton<AmenitiesProvider>(() => AmenitiesProvider());
  gh.factory<Client>(() => httpClientInjectableModule.client);
  gh.lazySingleton<FileProvider>(() => FileProvider());
  gh.lazySingleton<FlutterSecureStorage>(
      () => flutterStorageModule.secureStorate);
  gh.factory<ProfilePageBloc>(() => ProfilePageBloc());
  gh.factory<SplashScreenBloc>(() => SplashScreenBloc());
  gh.lazySingleton<AuthLocalDataSourceProtocol>(
      () => AuthLocalDataSource(secureStorage: get<FlutterSecureStorage>()));
  gh.lazySingleton<AuthRemoteDataSourceProtocol>(
      () => AuthRemoteDataSource(client: get<Client>()));
  return get;
}

Solution

  • In my config page.

    @injectableInit
    void configureInjection(String environment) {
      $initGetIt(getIt, environment: environment);
    }
    

    I just created a test environment and added following like, now its working as expected.

    @injectableInit
    void configureInjection(String environment) {
      $initGetIt(getIt, environment: environment);
      if (environment == Environment.test) {
        getIt.allowReassignment = true;
      }
    }