1

I am trying to write widget tests for my Flutter application.

I have a page (MainMenuScreen) as follows (I've left out the imports):

class MainMenuScreen extends StatefulWidget {
@override
   _MainMenuScreenState createState() => _MainMenuScreenState();
}

class _MainMenuScreenState extends State<MainMenuScreen> {
 @override
 void initState() {
   super.initState();
 }

 late MainMenuViewModel vm;
 @override
 Widget build(BuildContext context) {
  vm = Provider.of<MainMenuViewModel>(context);

  return Scaffold(
  backgroundColor: Colors.white,
  body: SafeArea(
      child: Center(
    child: Column(
      children: <Widget>[
        generateHeightSpacer(Dimensions().heightSpace),
        generateLogo(Dimensions().fractionalWidth),
        generateHeightSpacer(Dimensions().fractionalWidth),
        generateMenuButton(
            context,
            Dimensions().fractionalWidth,
            Dimensions().fractionalHeight,
            AppLocalizations.of(context).menuPlay,
            LevelSelectionScreen()),
        generateHeightSpacer(Dimensions().heightSpace),
        generateMenuButton(
            context,
            Dimensions().fractionalWidth,
            Dimensions().fractionalHeight,
            AppLocalizations.of(context).menuAbout,
            AboutScreen()),
      ],
    ),
  )),
);

} }

My main.dart file looks like this:

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => MainMenuViewModel()),
        ChangeNotifierProvider(create: (context) => LevelSelectionViewModel()),
        ChangeNotifierProvider(create: (context) => LevelViewModel()),
      ],
      child: MaterialApp(
        onGenerateTitle: (context) {
          return AppLocalizations.of(context).appTitle;
        },
        localizationsDelegates: [
          AppLocalizations.delegate,
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate,
        ],
        supportedLocales: [
          Locale('en', ''), // English, no country code
          Locale('es', ''), // Spanish, no country code
        ],
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: ChangeNotifierProvider(
          create: (context) => MainMenuViewModel(),
          child: MainMenuScreen(),
          // ),
        ),
      ),
    );
  }
}

I have looked into how to write a test that can identify when the About screen is displayed, i.e. after pressing the last Menu Button.

So, for now I have something as follows:

  testWidgets("Flutter Main Menu Test Menu Button About",
  (WidgetTester tester) async {
await tester.pumpWidget(MyApp());
var button = find.text("About");
expect(button, findsOneWidget);

});

This allows me to identify that the About button is displayed. (Note: I will be changing my code and tests to do this based on a 'key' rather than text.)

From what I've read the way to test is to use Mockito and a NavigationObserver but that seems to require the ability to inject into the screen. I have also been looking at other solutions which seem to suggest wrapping the provider, i.e.:

I've been following this page(https://iiro.dev/writing-widget-tests-for-navigation-events/) to try to test but I can't quite figure out how to pass the viewmodel in.

This is my test at the moment:

class MockMainMenuViewModel extends Mock implements MainMenuViewModel {}

class MockNavigatorObserver extends Mock implements NavigatorObserver {}

void main() {
  group('MainMenuScreen navigation tests', () {
    late NavigatorObserver mockObserver;
    MockMainMenuViewModel? mockViewModel;

    setUp(() {
      mockObserver = MockNavigatorObserver();
      mockViewModel = MockMainMenuViewModel();
    });

    Future<void> _buildMainPage(WidgetTester tester) {
      return tester.pumpWidget(MaterialApp(
        home: MainMenuScreen(mockViewModel),
        navigatorObservers: <NavigatorObserver>[observer],
      ));
    }

  });
}

Any help is appreciated please.

greysqrl
  • 937
  • 3
  • 13
  • 31

0 Answers0