为什么在像这样分配 Future 函数时,pumpAndSettle 会超时

Cal*_*ves 7 dart flutter flutter-test widget-test-flutter

在我的州立课上,我宣布了一个未来:

\n
Future<void> _testFuture;\n
Run Code Online (Sandbox Code Playgroud)\n

并像这样分配它initState

\n
super.initState();\n\n_testFuture = Future(() async {\n      await Future.value(1); //can be any computation\n    });\n
Run Code Online (Sandbox Code Playgroud)\n

并像这样使用它FutureBuilder

\n
 FutureBuilder(\n              future: _testFuture,\n              builder: (context, snapshot) {\n                if (snapshot.connectionState == ConnectionState.done)\n                  return Text('Hi');\n                else\n                  return Center(\n                    child: CircularProgressIndicator(),\n                  );\n              },\n            ),\n
Run Code Online (Sandbox Code Playgroud)\n

正常运行应用程序时效果很好,flutter run但是当我尝试使用以下方法测试小部件时flutter test test/widget_test.dart

\n
void main() {\n  testWidgets('Testing', (WidgetTester tester) async {\n    // Build our app and trigger a frame.\n    await tester.runAsync(() async {\n      await tester.pumpWidget(MyApp());\n      await tester.pumpAndSettle();\n    });\n}\n
Run Code Online (Sandbox Code Playgroud)\n

它失败了:

\n
\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa1 EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK \xe2\x95\x9e\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\nThe following assertion was thrown while running async test code:\npumpAndSettle timed out\n
Run Code Online (Sandbox Code Playgroud)\n

但是,如果我以这种方式分配未来,相同的测试将毫无问题地通过:

\n
super.initState();\n\nFuture<void> testFutures() async {\n      await Future.value(1);\n    }\n\n_testFuture = testFutures();\n
Run Code Online (Sandbox Code Playgroud)\n

这两种分配未来的方式有什么区别?

\n

Oma*_*att 4

默认超时为pumpAndSettle十分钟,如文档中所述。检查您的代码,测试应该运行良好。当我在本地尝试时,无论哪种方式初始化Future<void>都不会导致任何问题。

\n

这是您也可以尝试的示例。完成后应显示文本Future.delayed()。其中之一Future<void>是在 上初始化的initState()

\n
import \'package:flutter/material.dart\';\n\nvoid main() {\n  runApp(MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \'Flutter Demo\',\n      theme: ThemeData(\n        primarySwatch: Colors.blue,\n      ),\n      home: MyHomePage(title: \'Flutter Demo Home Page\'),\n    );\n  }\n}\n\nclass MyHomePage extends StatefulWidget {\n  MyHomePage({Key? key, required this.title}) : super(key: key);\n\n  final String title;\n\n  @override\n  _MyHomePageState createState() => _MyHomePageState();\n}\n\nclass _MyHomePageState extends State<MyHomePage> \n\n  late Future<void> _testFuture1;\n\n  Future<void> _testFuture2() async {\n    // await Future.value(1);\n    await Future.delayed(Duration(seconds: 5), () {\n      debugPrint(\'Test 2: \\"Hello from the future!\\"\');\n    });\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    _testFuture1 = Future(() async {\n      // await Future.value(1);\n      await Future.delayed(Duration(seconds: 5), () {\n        debugPrint(\'Test 1: \\"Hello from the future!\\"\');\n      });\n    });\n  }\n\n  FutureBuilder _futureBuilder1() {\n    return FutureBuilder(\n        future: _testFuture1,\n        builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {\n          if (snapshot.connectionState == ConnectionState.done)\n            return Text(\'Test 1 Done!\');\n          else\n            return Center(\n              child: CircularProgressIndicator(),\n            );\n          // return Text(\'Test 1 Done!\');\n        });\n  }\n\n  FutureBuilder _futureBuilder2() {\n    return FutureBuilder(\n        future: _testFuture2(),\n        builder: (BuildContext context, AsyncSnapshot<dynamic> builder) {\n          return Text(\'Test 2 Done!\');\n        });\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(widget.title),\n      ),\n      body: Center(\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.center,\n          children: <Widget>[\n            _futureBuilder1(),\n            _futureBuilder2(),\n          ],\n        ),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是测试文件

\n
void main() {\n  testWidgets(\'Future test\', (WidgetTester tester) async {\n    // Build our app and trigger a frame.\n    await tester.runAsync(() async{\n      await tester.pumpWidget(MyApp());\n      await tester.pump(); // both pump() and pumpAndSettle() works fine\n    }).then((value) {\n      // expect(find.text(\'Test 1 Done!\'), findsOneWidget);\n      // expect(find.text(\'Test 2 Done!\'), findsOneWidget);\n    });\n  });\n}\n
Run Code Online (Sandbox Code Playgroud)\n

演示

\n

测试

\n

测试

\n

这是我的 Flutter 版本供参考

\n
[\xe2\x9c\x93] Flutter (Channel stable, 2.2.1, on macOS 11.4 20F71 darwin-x64)\n    \xe2\x80\xa2 Flutter version 2.2.1\n    \xe2\x80\xa2 Framework revision 02c026b03c (6 weeks ago), 2021-05-27 12:24:44 -0700\n    \xe2\x80\xa2 Engine revision 0fdb562ac8\n    \xe2\x80\xa2 Dart version 2.13.1\n
Run Code Online (Sandbox Code Playgroud)\n