如何让小部件测试等到 Bloc 更新状态?
Posted
技术标签:
【中文标题】如何让小部件测试等到 Bloc 更新状态?【英文标题】:How to make widget test wait until Bloc has updated the state? 【发布时间】:2020-05-10 03:45:19 【问题描述】:我有一个EmailScreen
(有状态小部件),它有一个文本输入和一个按钮。该按钮仅在输入有效电子邮件时启用。
我正在使用 Bloc,我的屏幕有 InitialEmailState
和 ValidEmailInputState
,当我运行应用程序时它运行良好。
在我的小部件测试中,第二个期望在 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)
如您所见,它打印初始状态,第二次期望失败,然后打印期望状态。
提前致谢:)
== 更新 ==
我们通过在 main 开头添加 LiveTestWidgetsFlutterBinding();
来实现此功能。但这感觉不是一个好的解决方案。
【问题讨论】:
【参考方案1】:在使用 BLoC 驱动的 UI 小部件时遇到了同样的问题,我发现解决方案非常简单:使用 expectLater()
而不是 expect()
来等待 BLoC 状态更新:
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
。也就是说 BLoC 确实发出了一个新的状态,但是那个时候测试用例已经运行到最后了。
通过使用expectLater
,在发出新状态后对其进行评估。
【讨论】:
以上是关于如何让小部件测试等到 Bloc 更新状态?的主要内容,如果未能解决你的问题,请参考以下文章