错误“pumpAndSettle 超时”可能是由于 Riverpod 造成的

Fra*_*cca 14 dart flutter widget-test-flutter flutter-hooks riverpod

我被小部件测试困住了,我可以使用一些帮助
来重现该行为,请运行下面的代码示例

\n
import \'package:flutter/material.dart\';\nimport \'package:hooks_riverpod/hooks_riverpod.dart\';\nimport \'home_page.dart\';\n\nvoid main() => runApp(\n      const ProviderScope(\n        child: MaterialApp(\n          home: Material(\n            child: MyHomePage(),\n          ),\n        ),\n      ),\n    );\n
Run Code Online (Sandbox Code Playgroud)\n
import \'dart:math\';\nimport \'package:flutter/material.dart\';\nimport \'package:flutter_hooks/flutter_hooks.dart\';\nimport \'package:hooks_riverpod/hooks_riverpod.dart\';\n\nextension RoundX on double {\n  double roundToPrecision(int n) {\n    final f = pow(10, n);\n    return (this * f).round() / f;\n  }\n}\n\nfinal tasksPod = Provider<List<Future<void> Function()>>(\n  (ref) => [\n    for (var i = 0; i < 10; ++i)\n      () async {\n        await Future.delayed(kThemeAnimationDuration);\n      }\n  ],\n);\n\nfinal progressPod = Provider.autoDispose<ValueNotifier<double>>((ref) {\n  final notifier = ValueNotifier<double>(0);\n  ref.onDispose(notifier.dispose);\n  return notifier;\n});\n\nclass MyHomePage extends HookWidget {\n  const MyHomePage() : super(key: const ValueKey(\'MyHomePage\'));\n\n  @override\n  Widget build(BuildContext context) {\n    final progress = useProvider(progressPod);\n    final tasks = useProvider(tasksPod);\n    useMemoized(() async {\n      final steps = tasks.length;\n      if (steps < 1) {\n        progress.value = 1;\n      } else {\n        for (final task in tasks) {\n          final current = progress.value;\n          if (current >= 1) {\n            break;\n          }\n          await task();\n          final value = (current + 1 / steps).roundToPrecision(1);\n          print(\'$value\');\n          progress.value = value;\n        }\n      }\n    });\n    return Center(\n      child: ValueListenableBuilder<double>(\n        valueListenable: progress,\n        child: const FlutterLogo(),\n        builder: (context, value, child) =>\n            value < 1 ? const CircularProgressIndicator() : child!,\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

运行应用程序一切正常

\n
\xe2\x9c\x93  Built build/app/outputs/flutter-apk/app-debug.apk.\nInstalling build/app/outputs/flutter-apk/app.apk...                 4.7s\nSyncing files to device Pixel 3a...                                 93ms\n\nFlutter run key commands.\nr Hot reload. \nR Hot restart.\nh Repeat this help message.\nd Detach (terminate "flutter run" but leave application running).\nc Clear the screen\nq Quit (terminate the application on the device).\n\n Running with sound null safety \n\nAn Observatory debugger and profiler on Pixel 3a is available at: http://127.0.0.1:36517/50vVndYZ3l4=/\nI/flutter (19990): 0.1\nI/flutter (19990): 0.2\nI/flutter (19990): 0.3\nI/flutter (19990): 0.4\nI/flutter (19990): 0.5\nI/flutter (19990): 0.6\nI/flutter (19990): 0.7\nThe Flutter DevTools debugger and profiler on Pixel 3a is available at: http://127.0.0.1:9101?uri=http%3A%2F%2F127.0.0.1%3A36517%2F50vVndYZ3l4%3D%2F\nI/flutter (19990): 0.8\nI/flutter (19990): 0.9\nI/flutter (19990): 1.0\nApplication finished.\n\n
Run Code Online (Sandbox Code Playgroud)\n

但没有通过这个测试

\n
import \'package:flutter/material.dart\';\nimport \'package:flutter_test/flutter_test.dart\';\nimport \'package:hooks_riverpod/hooks_riverpod.dart\';\nimport \'package:timeout_issue/home_page.dart\';\n\nvoid main() {\n  testWidgets(\n      \'WHEN tasks are not completed\'\n      \'THEN shows `CircularProgressIndicator`\', (tester) async {\n    TestWidgetsFlutterBinding.ensureInitialized();\n\n    await tester.runAsync(() async {\n      await tester.pumpWidget(\n        ProviderScope(\n          child: const MaterialApp(\n            home: Material(\n              child: MyHomePage(),\n            ),\n          ),\n        ),\n      );\n\n      await tester.pumpAndSettle(kThemeAnimationDuration);\n\n      expect(\n        find.byType(CircularProgressIndicator),\n        findsOneWidget,\n        reason: \'CircularProgressIndicator should be shown\',\n      );\n    });\n  });\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

有了这个输出

\n
00:05 +0: WHEN tasks are not completedTHEN shows `CircularProgressIndicator`                                                                                                                                \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\nWhen the exception was thrown, this was the stack:\n#0      WidgetTester.pumpAndSettle.<anonymous closure> (package:flutter_test/src/widget_tester.dart:651:11)\n<asynchronous suspension>\n<asynchronous suspension>\n(elided one frame from package:stack_trace)\n...\n\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\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\n00:05 +0 -1: WHEN tasks are not completedTHEN shows `CircularProgressIndicator` [E]                                                                                                                         \n  Test failed. See exception logs above.\n  The test description was: WHEN tasks are not completedTHEN shows `CircularProgressIndicator`\n  \n00:05 +0 -1: Some tests failed.                \n
Run Code Online (Sandbox Code Playgroud)\n
\n

环境是

\n

Flutter version 2.2.0-11.0.pre.176

\n
environment:\n  sdk: ">=2.12.0 <3.0.0"\n\ndependencies:\n  flutter:\n    sdk: flutter\n  hooks_riverpod: ^0.14.0\n  flutter_hooks: ^0.16.0\n
Run Code Online (Sandbox Code Playgroud)\n

感谢任何帮助

\n

Mar*_*yns 26

我想说这个问题与使用 PumpAndSettle 和无限动画(圆形进度指示器)有关。您可以尝试使用不带沉降器的泵自行构建框架。

https://api.flutter.dev/flutter/flutter_test/WidgetTester/pumpAndSettle.html


Cat*_*lin 9

看来 atm Riverpod 和 PumpAndSettle 不起作用,作为一个令人讨厌的快速黑客,你可以尝试这样的事情:

for (int i = 0; i < 5; i++) {
  // because pumpAndSettle doesn't work with riverpod
  await tester.pump(Duration(seconds: 1));
}
Run Code Online (Sandbox Code Playgroud)