Mul*_*dec 13 error-handling dart flutter flutter-test
I'm facing an issue while doing widget testing on a widget that throws an exception during a Future
.
Code to reproduce the problem
Here's a simple testwidget that reproduces the problem in a very simple way (thanks to Remi Rousselet for the simplification of the problem).
testWidgets('This test should pass but fails', (tester) async {
final future = Future<void>.error(42);
await tester.pumpWidget(FutureBuilder(
future: future,
builder: (_, snapshot) {
return Container();
},
));
});
Run Code Online (Sandbox Code Playgroud)
Expected result
我希望测试能够顺利完成。相反,它失败并显示以下错误:
??? EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ?????????????????????????????????????????????????????
The number 42 was thrown running a test.
When the exception was thrown, this was the stack:
#2 main.<anonymous closure> (file:///C:/Projects/projet_65/mobile_app/test/ui/exception_test.dart:79:18)
#5 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:0:0)
#8 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:577:14)
#9 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:993:24)
#15 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:990:15)
#16 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:106:22)
#17 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:27)
#20 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:0:0)
#21 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:250:15)
#27 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:399:21)
(elided 17 frames from class _FakeAsync, package dart:async, and package dart:async-patch)
The test description was:
This test should pass but fails
????????????????????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
我尝试过的
我尝试expect
过错误,就像如果不在Future
with中一样:
??? EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ?????????????????????????????????????????????????????
The number 42 was thrown running a test.
When the exception was thrown, this was the stack:
#2 main.<anonymous closure> (file:///C:/Projects/projet_65/mobile_app/test/ui/exception_test.dart:79:18)
#5 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:0:0)
#8 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:577:14)
#9 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:993:24)
#15 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:990:15)
#16 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:106:22)
#17 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:27)
#20 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:0:0)
#21 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:250:15)
#27 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:399:21)
(elided 17 frames from class _FakeAsync, package dart:async, and package dart:async-patch)
The test description was:
This test should pass but fails
????????????????????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
但是该语句失败,并出现以下错误
expect(tester.takeException(), equals(42));
Run Code Online (Sandbox Code Playgroud)
编辑:
@shb答案对于暴露的情况是正确的。这是一个略微的修改,可以打破它并退回初始错误。这种情况在实际应用中更容易发生(对我来说就是这种情况)
The following TestFailure object was thrown running a test (but after the test had completed):
Expected: 42
Actual: null
Run Code Online (Sandbox Code Playgroud)
注意:我自愿忽略了@shb tester.runAsync
提出的建议,以匹配最初的问题,因为它在特定情况下不起作用
用以下代码包装您的代码 await tester.runAsync(() async { .. }
从官方文档 runAsync<T>
运行执行实际异步工作的回调。
这适用于需要调用异步方法的调用方,这些方法产生隔离或OS线程,因此无法通过调用pump同步执行。
见下文
testWidgets('This test should pass but fails', (tester) async {
await tester.runAsync(() async {
final future = Future<void>.error(42);
await tester.pumpWidget(FutureBuilder(
future: future,
builder: (_, snapshot) {
return Container();
},
));
});
});
Run Code Online (Sandbox Code Playgroud)
编辑:
(第二期OP)
在这种情况下使用
Future.delayed(Duration.zero, () {
tester.tap(find.text('GO'));
});
Run Code Online (Sandbox Code Playgroud)
下面的完整代码段
testWidgets('2nd try This test should pass but fails', (tester) async {
Future future;
await tester.runAsync(() async {
await tester.pumpWidget(
MaterialApp(
home: Row(
children: <Widget>[
FlatButton(
child: const Text('GO'),
onPressed: () {
future = Future.error(42);
},
),
FutureBuilder(
future: future,
builder: (_, snapshot) {
return Container();
},
),
],
),
),
);
Future.delayed(Duration.zero, () {tester.tap(find.text('GO'));});
});
});
Run Code Online (Sandbox Code Playgroud)
编辑2:
后来发现
Future.delayed(Duration.zero, () { tester.tap(find.text('GO')); });
没有被调用。
期货向听众报告错误。如果a Future
没有监听器,则会通知尚未Zone
捕获的错误(src)。这是测试框架从中获取错误的地方。
解决这个错误的一种方法是在监听错误前等待听众Future
。
testWidgets('This passes', (tester) async {
final Completer completer = Completer();
await tester.pumpWidget(FutureBuilder(
future: completer.future,
builder: (_, snapshot) {
return Container();
},
));
// has subscribers, doesn't inform Zone about uncought error
completer.completeError(42);
tester.pumpAndSettle();
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1250 次 |
最近记录: |