Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to make widget tests pass with auto_route and getIt #1619

Closed
seriann opened this issue Jun 22, 2023 · 3 comments
Closed

Unable to make widget tests pass with auto_route and getIt #1619

seriann opened this issue Jun 22, 2023 · 3 comments

Comments

@seriann
Copy link

seriann commented Jun 22, 2023

Hello everyone,

I'm having difficulty getting the widget tests to pass with auto_route and getIt.
i've found possible solutions on these issues #1138, #745 .
I also tried the solution mentioned in this comment: #1138 (comment), but unfortunately none of these worked for me.

Router:

part 'app_routes.gr.dart';

@AutoRouterConfig(
  replaceInRouteName: 'Page|Screen,Route'
)      
class AppRouter extends _$AppRouter {      
   
 @override
 RouteType get defaultRouteType => RouteType.material();

 @override      
 List<AutoRoute> get routes => [
    AutoRoute(page: HomeRoute.page, path: Routes.home),
    AutoRoute(page: DashboardRoute.page, path: Routes.dashboard, guards: [AuthGuard()]),
  ];
}

GetIt Instance

injection_container.dart

final dependencyInjector = GetIt.instance;

Future<void> init() async {
  initAppRouter();
}

void initAppRouter() {
  dependencyInjector.registerSingleton<AppRouter>(AppRouter());
}

Main.dart:

main.dart

Future<void> main() async {
  await init();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  MyApp({super.key});
  final _appRouter = dependencyInjector<AppRouter>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routeInformationParser: _appRouter.defaultRouteParser(),
      routerDelegate: AutoRouterDelegate(_appRouter),
    );
  }
}

Test with auto_route and get_it:

import 'package:project/core/domain/routes/app_routes.dart' as router;
import 'package:project/injection_container.dart';

import 'skip_dashboard_test.mocks.dart';

@GenerateNiceMocks([MockSpec<router.AppRouter>()])
void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  WidgetsFlutterBinding.ensureInitialized();
  final mockAppRouter = MockAppRouter();

  setUpAll(() async {
    dependencyInjector.registerSingleton<router.AppRouter>(mockAppRouter);
  });

  group(
    "When click on SkipDashboard widget",
    () {
      testWidgets('It should navigate to home page',
          (WidgetTester tester) async {
        when(dependencyInjector<router.AppRouter>().push(router.HomeRoute()))
            .thenAnswer((_) async => {});

        await tester.pumpWidget(MaterialApp(home: SkipDashboard()));

        expect(find.text('Omitir', skipOffstage: false), findsOneWidget);

        await tester.tap(find.text('Omitir'));
        await tester.pumpAndSettle();

        verify(() =>
            dependencyInjector<router.AppRouter>().push(router.HomeRoute()));
      });
    },
  );
}

this test returns error:

The following _TypeError was thrown running a test:
type 'Null' is not a subtype of type 'Future<Object?>'

When the exception was thrown, this was the stack:
#0      MockAppRouter.push (file:///C:/Users/Usuario/Documents/project/test/dashboard/presentation/widgets/skip_dashboard_test.mocks.dart:34:7) 
#1      main.<anonymous closure>.<anonymous closure> (file:///C:/Users/Usuario/Documents/project/test/dashboard/presentation/widgets/skip_dashboard_test.dart:27:53)
#2      testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:170:29)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)

Mocks were created with mockito library.

I don't know if the solutions mentioned in the referenced issues above are outdated or incompatible with the current version of the auto_route library or i'm wrong on some configuration

@n0ks
Copy link

n0ks commented Jun 23, 2023

I'm not very familiar with mockito, but I do write tests using mocktail. The code bellow works for me.

      when(() => sl<AppRouter>().push(const HomeTabRoute()))
          .thenAnswerWithVoid();

thenAnswerWithVoid is just an extension to the following

  void thenAnswerWithVoid() => thenAnswer((_) => Future<void>.value());

@Milad-Akarie
Copy link
Owner

@seriann @n0ks I'm doing the following in AutoRoute internal tests

  late SimpleRouter router;
  setUp(() {
    // Setting ignore pop completes to true will not return the actual
    // route pop completer but a SynchronousFuture(null);
    router = SimpleRouter()..ignorePopCompleters = true;  
  });

  test( 'Pushing single route should add it to the top of stack', () async {
     await router.push(const FirstRoute());
     expect(router.current.name, FirstRoute.name);

      /// or check the whole current hiererchy
     expect(router.currentHierarchy(), const [
       HierarchySegment(FirstRoute.name),
     ]);
  });

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants