如何进行小部件测试,直到Bloc更新状态?

时间:2020-01-23 19:33:03

标签: testing flutter bloc

我有一个EmailScreen(有状态的小部件),它具有文本输入和一个按钮。仅当输入有效的电子邮件时,该按钮才启用。

我正在使用Bloc,并且屏幕上有InitialEmailStateValidEmailInputState,并且在运行该应用程序时可以正常工作。

在我的小部件测试中,第二个期望失败了,而bloc才有机会更新状态:


  testWidgets('when valid email is input, button is enabled', (tester) async {
    const validEmail = 'email@provider.com';

    emailBloc.listen((event) {
      print('NEW EVENT: ' + event.toString());
    });

    await bootUpWidget(tester, emailScreen);

    final BottomButton button = tester.widget(
        find.widgetWithText(BottomButton, 'CONTINUE'));

    expect(button.enabled, isFalse);

    await tester.enterText(find.byType(TextInputScreen), validEmail);
    await tester.pumpAndSettle();

    expect(button.enabled, isTrue);
  });

这是我得到的输出:

NEW EVENT: InitialEmailState
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected: true
  Actual: <false>

...

The test description was:
  when valid email is input, button is enabled
════════════════════════════════════════════════════════════════════════════════════════════════════
Test failed. See exception logs above.
The test description was: when valid email is input, button is enabled

NEW EVENT: InputValidEmailState
✖ when valid email is input, button is enabled
Exited (1)

如您所见,它将打印初始状态,不满足第二个期望,然后打印期望状态。

预先感谢:)

==更新==

我们通过在主程序的开头添加LiveTestWidgetsFlutterBinding();来使其正常工作。但这并不是一个好的解决方案。

1 个答案:

答案 0 :(得分:0)

在BLoC驱动的UI小部件中遇到相同的问题,我发现解决方案非常简单:使用expect()而不是testWidgets('test widgets driven by BLoC', (tester) async { await tester.pumpWidget(yourWidget); await tester.tap(loginButton); // Do something like tapping a button, entering text await tester.pumpAndSettle(); await expectLater(findSomething, findsOneWidget); // IMPRTANT: use `expectLater` to wait for BLoC state update expect(findSomethingElse, findsOneWidget); // Subsequently you can use normal version `expect` until next `tester.pumpAndSettle()` } 来等待BLoC状态更新:

expectLater

我在BLoC中放置了断点以找出问题所在,事实证明,在不使用expect的情况下,正常的expectLater会在BLoC流发出新状态之前进行评估。也就是说,BLoC确实发出了一个新状态,但那时测试用例已经运行到最后。

通过使用useEffect,在发出新状态后对其进行评估。