【问题标题】:Test failing on BlocListener in flutter when testing widget测试小部件时在颤动中测试 BlocListener 失败
【发布时间】:2020-03-01 17:38:52
【问题描述】:

我有两个测试来检查在使用 BlocListener 流式传输和处理登录状态时是否显示小吃店。

void main() async {
  AuthenticationRepositoryMock _authenticationRepositoryMock;
  LoginBlocMock _loginBloc;
  final fireBaseUserMock = FirebaseUserMock();
  final randomValidPassword = "password";
  final buttonFinder = find.byKey(Key('credentials_button'));
  final snackBarFailureFinder = find.byKey(Key("snack_bar_failure"));
  final snackBarLoadingFinder = find.byKey(Key("snack_bar_loading"));
  final emailFieldFinder = find.byKey(Key('email_field'));
  final passwordFieldFinder = find.byKey(Key('password_field'));

  Widget makeTestableWidget() {
    return BlocProvider<LoginBloc>(
      builder: (context) => _loginBloc,
      child: MaterialApp(
        home: Scaffold(
          body: LoginPage(),
        )
      ),
    );
  }

  setUp((){
    _authenticationRepositoryMock = AuthenticationRepositoryMock();
    _loginBloc = LoginBlocMock(authenticationRepository: _authenticationRepositoryMock);
  });

  testWidgets('Show snack bar when state is LoginFailure', (WidgetTester tester) async {

    //Arrange
    var expectedStates = [
      LoginInitial(), 
      LoginFailure(error: "Could not find user. Please try different credentials")
    ];

    whenListen(_loginBloc, Stream.fromIterable(expectedStates));

    //Act
    await tester.pumpWidget(makeTestableWidget());

    expect(snackBarFailureFinder, findsNothing);

    await tester.enterText(emailFieldFinder, fireBaseUserMock.email);
    await tester.pumpAndSettle();

    await tester.enterText(passwordFieldFinder, randomValidPassword);
    await tester.pumpAndSettle();

    await tester.tap(buttonFinder);
    await tester.pumpAndSettle();

    //Assert
    expect(snackBarFailureFinder, findsOneWidget);
  });

  //FAILING FOR NO REASON!
  testWidgets('Show snack bar when state is LoginLoading', (WidgetTester tester) async {

    //Arrange
    var expectedStates = [
      LoginInitial(), 
      LoginLoading()
    ];

    whenListen(_loginBloc, Stream.fromIterable(expectedStates));

    //Act
    await tester.pumpWidget(makeTestableWidget());

    expect(snackBarLoadingFinder, findsNothing);

    await tester.enterText(emailFieldFinder, fireBaseUserMock.email);
    await tester.pumpAndSettle();

    await tester.enterText(passwordFieldFinder, randomValidPassword);
    await tester.pumpAndSettle();

    await tester.tap(buttonFinder);
    await tester.pumpAndSettle();

    //Assert
    expect(snackBarLoadingFinder, findsOneWidget);
  });
}

而这两个测试正在测试页面上的以下小部件:

BlocListener<LoginBloc, LoginState>(
              listener: (context, state){
                if(state is LoginFailure){
                  Scaffold.of(context)
                    .showSnackBar(SnackBar(
                      key: Key("snack_bar_failure"),
                      content: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [Text('Login Failure'), Icon(Icons.error)],
                      ),
                      backgroundColor: Colors.redAccent
                    ));
                }

                if (state is LoginLoading) {
                  Scaffold.of(context)
                    .showSnackBar(SnackBar(
                      key: Key("snack_bar_loading"),
                      content: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [Text('Logging in...'), Spinner()],
                      ),
                      backgroundColor: Colors.blueAccent
                    ));
                }
              }

查找带有键“snack_bar_failure”的小吃店的第一个测试通过,但第二个测试没有通过。字面上是一样的测试,一样的设置,只是预期的状态不一样,小吃店的key不一样snack_bar_loading

第二次测试失败并显示以下错误消息:

The following TestFailure object was thrown running a test:
  Expected: exactly one matching node in the widget tree
  Actual: ?:<zero widgets with key [<'snack_bar_loading'>] (ignoring offstage widgets)>    
   Which: means none were found but one was expected

我错过了什么吗?

【问题讨论】:

    标签: flutter bloc flutter-test


    【解决方案1】:

    问题已在问题 (https://github.com/felangel/bloc/issues/655) 中得到解答。希望对您有所帮助!

    【讨论】:

    • 我从您发布的内容和我的初始测试中看到的唯一区别是您使用了tester.pump() 而不是tester.pumpAndSettle()。这两者有什么区别?
    • tester.pumpAndSettle 重复调用pump 直到没有更多的调度帧,而tester.pump 只触发一个帧。我发布的内容与原始测试之间的主要区别在于您有多个 pumpAndSettles,它们都是不必要的,并导致 SnackBar 在执行 expect 之前被显示和关闭。
    猜你喜欢
    • 2022-12-13
    • 2021-01-31
    • 1970-01-01
    • 2021-02-22
    • 1970-01-01
    • 2019-05-23
    • 2020-04-11
    • 2020-12-06
    • 2018-07-07
    相关资源
    最近更新 更多