我如何测试颤抖的bloclistener导航并呈现一个初始欢迎页面

发布于 2025-01-26 21:39:19 字数 3897 浏览 3 评论 0原文

我试图测试我的应用程序首次运行并且尚未发生身份验证时发现一个欢迎页面小部件。

无论我尝试什么,我都无法验证小部件是否会呈现。

测试每次都失败。我正在使用期望(find.bytype(欢迎页),findsonewidget);

错误:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _WidgetTypeFinder:<zero widgets with type "WelcomePage" (ignoring offstage widgets)>
Which: means none were found but one was expected

测试代码:

class MockAuthenticationBloc
    extends MockBloc<AuthenticationEvent, AuthenticationState>
    implements AuthenticationBloc {}

void main() {
  group('App', () {
    late AuthenticationBloc authenticationBloc;

    setUp(() {
      authenticationBloc = MockAuthenticationBloc();
    });

    group('Unauthenticated', () {
      testWidgets('displays the WelcomeScreen', (tester) async {
        when(() => authenticationBloc.state)
            .thenReturn(const AuthenticationState.unauthenticated());
        await tester.pumpApp(
          Scaffold(
            body: BlocProvider.value(
              value: authenticationBloc,
              child: const AppView(),
            ),
          ),
        );

        expect(find.byType(WelcomePage), findsOneWidget);
      });
    });
  });
}

app.dart

class App extends StatelessWidget {
  const App({
    Key? key,
    required this.authenticationRepository,
    required this.userRepository,
  }) : super(key: key);

  final AuthenticationRepository authenticationRepository;
  final UserRepository userRepository;

  @override
  Widget build(BuildContext context) {
    return RepositoryProvider.value(
      value: authenticationRepository,
      child: BlocProvider(
        create: (_) => AuthenticationBloc(
          authenticationRepository: authenticationRepository,
          userRepository: userRepository,
        ),
        child: const AppView(),
      ),
    );
  }
}

class AppView extends StatefulWidget {
  const AppView({Key? key}) : super(key: key);

  @override
  // ignore: library_private_types_in_public_api
  _AppViewState createState() => _AppViewState();
}

class _AppViewState extends State<AppView> {
  final _navigatorKey = GlobalKey<NavigatorState>();

  NavigatorState get _navigator => _navigatorKey.currentState!;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: _navigatorKey,
      theme: ThemeData(
        appBarTheme:
            const AppBarTheme(color: Color.fromARGB(255, 214, 39, 185)),
        colorScheme: ColorScheme.fromSwatch(
          accentColor: const Color.fromARGB(255, 241, 136, 255),
        ),
      ),
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: AppLocalizations.supportedLocales,
      builder: (context, child) {
        return BlocListener<AuthenticationBloc, AuthenticationState>(
          listener: (context, state) {
            switch (state.status) {
              case AuthenticationStatus.authenticated:
                _navigator.pushAndRemoveUntil<void>(
                  HomePage.route(),
                  (route) => false,
                );
                break;
              case AuthenticationStatus.unauthenticated:
                _navigator.pushAndRemoveUntil<void>(
                  WelcomePage.route(),
                  (route) => false,
                );
                break;
              case AuthenticationStatus.unknown:
                break;
            }
          },
          child: child,
        );
      },
      onGenerateRoute: (_) => SplashPage.route(),
    );
  }
}

I am trying to test that a WelcomePage widget is found when my App is first run and no authentication has yet happened.

No matter what I try, I cannot verify that the widget gets rendered.

The test fails every time. I am using expect(find.byType(WelcomePage), findsOneWidget);

Error:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _WidgetTypeFinder:<zero widgets with type "WelcomePage" (ignoring offstage widgets)>
Which: means none were found but one was expected

Test Code:

class MockAuthenticationBloc
    extends MockBloc<AuthenticationEvent, AuthenticationState>
    implements AuthenticationBloc {}

void main() {
  group('App', () {
    late AuthenticationBloc authenticationBloc;

    setUp(() {
      authenticationBloc = MockAuthenticationBloc();
    });

    group('Unauthenticated', () {
      testWidgets('displays the WelcomeScreen', (tester) async {
        when(() => authenticationBloc.state)
            .thenReturn(const AuthenticationState.unauthenticated());
        await tester.pumpApp(
          Scaffold(
            body: BlocProvider.value(
              value: authenticationBloc,
              child: const AppView(),
            ),
          ),
        );

        expect(find.byType(WelcomePage), findsOneWidget);
      });
    });
  });
}

app.dart

class App extends StatelessWidget {
  const App({
    Key? key,
    required this.authenticationRepository,
    required this.userRepository,
  }) : super(key: key);

  final AuthenticationRepository authenticationRepository;
  final UserRepository userRepository;

  @override
  Widget build(BuildContext context) {
    return RepositoryProvider.value(
      value: authenticationRepository,
      child: BlocProvider(
        create: (_) => AuthenticationBloc(
          authenticationRepository: authenticationRepository,
          userRepository: userRepository,
        ),
        child: const AppView(),
      ),
    );
  }
}

class AppView extends StatefulWidget {
  const AppView({Key? key}) : super(key: key);

  @override
  // ignore: library_private_types_in_public_api
  _AppViewState createState() => _AppViewState();
}

class _AppViewState extends State<AppView> {
  final _navigatorKey = GlobalKey<NavigatorState>();

  NavigatorState get _navigator => _navigatorKey.currentState!;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: _navigatorKey,
      theme: ThemeData(
        appBarTheme:
            const AppBarTheme(color: Color.fromARGB(255, 214, 39, 185)),
        colorScheme: ColorScheme.fromSwatch(
          accentColor: const Color.fromARGB(255, 241, 136, 255),
        ),
      ),
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: AppLocalizations.supportedLocales,
      builder: (context, child) {
        return BlocListener<AuthenticationBloc, AuthenticationState>(
          listener: (context, state) {
            switch (state.status) {
              case AuthenticationStatus.authenticated:
                _navigator.pushAndRemoveUntil<void>(
                  HomePage.route(),
                  (route) => false,
                );
                break;
              case AuthenticationStatus.unauthenticated:
                _navigator.pushAndRemoveUntil<void>(
                  WelcomePage.route(),
                  (route) => false,
                );
                break;
              case AuthenticationStatus.unknown:
                break;
            }
          },
          child: child,
        );
      },
      onGenerateRoute: (_) => SplashPage.route(),
    );
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

刘备忘录 2025-02-02 21:39:19

我认为您必须等待您的小部件构建几帧并安顿下来,因此添加等待tester.pumpandsettle();

...
        await tester.pumpApp(
          Scaffold(
            body: BlocProvider.value(
              value: authenticationBloc,
              child: const AppView(),
            ),
          ),
        );
// HERE
await tester.pumpAndSettle();
// HERE
        expect(find.byType(WelcomePage), findsOneWidget);
      });
    });
  });
}

这样,您让Flutter构建了bloclistener的必要帧来执行并显示适当的页面。

I think you have to wait for your widget to build for a few frames and settle so add await tester.pumpAndSettle(); :

...
        await tester.pumpApp(
          Scaffold(
            body: BlocProvider.value(
              value: authenticationBloc,
              child: const AppView(),
            ),
          ),
        );
// HERE
await tester.pumpAndSettle();
// HERE
        expect(find.byType(WelcomePage), findsOneWidget);
      });
    });
  });
}

That way you let flutter build the necessary frames for the blocListener to execute and display the appropiate page.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文