ota*_*iao 5 dart dart-io flutter flutter-test
我正在为我的 Flutter 应用程序编写单元测试,但在读取 json 文件时遇到一些问题。我有一些 json 文件供我的 api 模拟类使用。每当我调用 File 对象上的方法时,它永远不会结束,但测试会继续执行,并以错误结束,因为它没有从文件对象接收数据。这很奇怪,因为只有当从小部件调用的提供程序调用模拟 api 方法时才会发生这种情况。如果我直接调用模拟 api 方法进行测试,则效果很好。\n我的应用程序的结构如下:WidgetScreen调用->提供商调用->mockApi。
\n\nWidget LegislacaoScreen 从我的提供者调用方法 carregarLegislacao,该方法又从我的 mockApi 调用方法 getLegislacaoes,该方法从 json 文件读取并将结果返回给提供者,然后通知我的小部件。任何帮助表示赞赏。
\n\n哦,我正在使用以下命令运行测试:flutter test test/my_test.dart
\n\n这里有一些代码:
\n\nLegislacaoScreen:
\n\nclass LegislacaoScreen extends StatefulWidget {\n @override\n _LegislacaoScreenState createState() => _LegislacaoScreenState();\n}\n\nclass _LegislacaoScreenState extends State<LegislacaoScreen>\n with AutomaticKeepAliveClientMixin {\n @override\n void initState() {\n super.initState();\n Future.microtask(carregarDados);\n }\n\n @override\n bool get wantKeepAlive => true;\n\n Future<void> carregarDados({bool reset = false}) async {\n try {\n final legislacaoProvider =\n Provider.of<LegislacaoProvider>(context, listen: false);\n\n await legislacaoProvider.carregarLegislacao(\n page: legislacaoProvider.currentPage + 1,\n reset: reset,\n );\n } catch (err) {}\n }\n\n Widget renderBody(legislacaoProvider) {\n if (legislacaoProvider.carregandoLegislacao &&\n legislacaoProvider.legislacoes.isEmpty &&\n !legislacaoProvider.reseting) {\n return Center(\n child: CircularProgressIndicator(),\n );\n }\n\n if (legislacaoProvider.erroCarregandoLegislacao) {\n return MensagemAcao(\n mensagem:\n \'Houve um erro ao carregar os dados.\\nPor favor tente novamente.\',\n acao: () => carregarDados(reset: true),\n );\n }\n\n return LegislacaoLista(\n carregandoLegislacao: legislacaoProvider.carregandoLegislacao,\n legislacoes: legislacaoProvider.legislacoes,\n reseting: legislacaoProvider.reseting,\n carregarDados: carregarDados,\n isFiltroEmpty: legislacaoProvider.isFiltroEmpty,\n );\n }\n\n @override\n Widget build(BuildContext context) {\n super.build(context);\n\n final legislacaoProvider = Provider.of<LegislacaoProvider>(context);\n\n return Scaffold(\n appBar: CustomAppBar(\n title: \'Legisla\xc3\xa7\xc3\xa3o\',\n actions: <Widget>[\n IconButton(\n icon: Icon(\n Icons.search,\n color: legislacaoProvider.isFiltroEmpty\n ? Colors.white\n : CustomColors.verde2,\n ),\n onPressed: () {\n Navigator.of(context)\n .pushNamed(PesquisarLegislacaoScreen.routeName);\n },\n ),\n ],\n ),\n backgroundColor: Colors.white,\n body: renderBody(legislacaoProvider),\n );\n }\nRun Code Online (Sandbox Code Playgroud)\n\n提供商:
\n\nclass LegislacaoProvider with ChangeNotifier {\n bool _carregandoLegislacao = true;\n bool _erroCarregandoLegislacao = false;\n List<Legislacao> legislacoes = [];\n int currentPage = 0;\n bool _reseting = false;\n\n LegislacaoApi _legislacaoApi;\n\n LegislacaoProvider({LegislacaoApi legislacaoApi})\n : _legislacaoApi = legislacaoApi ?? LegislacaoApiService();\n\n bool get carregandoLegislacao {\n return _carregandoLegislacao;\n }\n\n bool get erroCarregandoLegislacao {\n return _erroCarregandoLegislacao;\n }\n bool get reseting {\n return _reseting;\n }\n Future<void> carregarLegislacao({\n int page = 1,\n bool reset = false,\n }) async {\n try {\n _carregandoLegislacao = true;\n _erroCarregandoLegislacao = false;\n _reseting = reset;\n\n if (reset) {\n page = 1;\n }\n notifyListeners();\n legislacoes = await _legislacaoApi.getLegislacoes(\n page: page,\n ementa: filtro[\'ementa\'],\n conteudo: filtro[\'conteudo\'],\n ano: filtro[\'ano\'],\n periodoInicialLegislacao: filtro[\'periodoInicialLegislacao\'],\n periodoFinalLegislacao: filtro[\'periodoFinalLegislacao\'],\n tipoLegislacao: filtro[\'tipoLegislacao\']?.id,\n numero: filtro[\'numero\'],\n autor: filtro[\'autor\'],\n );\n _carregandoLegislacao = false;\n _reseting = false;\n notifyListeners();\n } catch (err) {\n print(err);\n _erroCarregandoLegislacao = true;\n _carregandoLegislacao = false;\n _reseting = false;\n notifyListeners();\n throw TaNaLeiException(err.toString());\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n模拟API:
\n\nclass LegislacaoApiServiceMock extends LegislacaoApi {\n bool _fail = false;\n\n LegislacaoApiServiceMock();\n\n LegislacaoApiServiceMock.fail() : _fail = true;\n\n @override\n Future<List<Legislacao>> getLegislacoes({\n int page = 1,\n String conteudo,\n String ementa,\n String ano,\n DateTime periodoInicialLegislacao,\n DateTime periodoFinalLegislacao,\n int tipoLegislacao,\n String numero,\n String autor,\n }) async {\n if (_fail) {\n throw Error();\n }\n\n\n final file = File(\'test/data/get_legislacoes.json\');\n print(\'step 1\');\n final json = await file.readAsString();\n print(\'step 2 \'); // <-- NEVER GETS PRINTED\n return jsonDecode(json)\n .map<Legislacao>(\n (elemento) => Legislacao.fromJson(elemento),\n )\n .toList();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n最后,我的测试:
\n\nfinal locator = GetIt.instance;\n\nvoid setupLocatorLegislacaoProvider({LegislacaoApi legislacaoApi}) {\n locator.registerLazySingleton<LegislacaoProvider>(() => LegislacaoProvider(\n legislacaoApi: legislacaoApi,\n ));\n}\n\n\nvoid main() async {\n TestWidgetsFlutterBinding.ensureInitialized();\n setupLocatorLegislacaoProvider(legislacaoApi: LegislacaoApiServiceMock());\n group(\'LegislacaoScreen\', () {\n Widget buildWidget() {\n return ChangeNotifierProvider.value(\n value: locator<LegislacaoProvider>();,\n child: MaterialApp(\n home: LegislacaoScreen(),\n routes: routes,\n ),\n );\n }\n\n testWidgets(\'builds screen\', (WidgetTester tester) async {\n final child = buildWidget();\n await tester.pumpWidget(child);\n\n expect(find.byWidget(child), findsOneWidget);\n });\n\n\n\n testWidgets(\'finds list when data is loaded\',\n (WidgetTester tester) async {\n await tester.pumpWidget(buildWidget());\n\n await tester.pump();\n await tester.pump();\n\n expect(find.byType(LegislacaoLista), findsOneWidget);\n });\n });\n}\nRun Code Online (Sandbox Code Playgroud)\n\n编辑:
\n\n这是运行测试时出现的错误消息:
\n\n\xe2\x9e\x9c ta_na_lei git:(testes) \xe2\x9c\x97 flutter test test/ui/screens/legislacao/legislacao_screen_test.dart\n00:03 +0: LegislacaoScreen builds screen \ndentro de mock 1\n00:04 +1: LegislacaoScreen exibe circular progress indicator quando carregando legislacao e reset true \ndentro de mock 1\n00:04 +2: LegislacaoScreen exibe lista de legislacao quando legislacoes carregadas \ndentro de mock 1\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 TestFailure object was thrown running a test:\n Expected: exactly one matching node in the widget tree\n Actual: _WidgetTypeFinder:<zero widgets with type "LegislacaoLista" (ignoring offstage widgets)>\n Which: means none were found but one was expected\n\nWhen the exception was thrown, this was the stack:\n#4 main.<anonymous closure>.<anonymous closure> (file:///Users/home/Projetos/casacivil/ta_na_lei/test/ui/screens/legislacao/legislacao_screen_test.dart:49:7)\n<asynchronous suspension>\n#5 main.<anonymous closure>.<anonymous closure> (file:///Users/home/Projetos/casacivil/ta_na_lei/test/ui/screens/legislacao/legislacao_screen_test.dart)\n#6 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)\n<asynchronous suspension>\n#7 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart)\n#8 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:703:19)\n<asynchronous suspension>\n#11 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:683:14)\n#12 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1083:24)\n#18 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1080:15)\n#19 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)\n#20 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:172:27)\n<asynchronous suspension>\n#21 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)\n#22 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:246:15)\n#27 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:243:5)\n#28 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:170:33)\n#33 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:13)\n#34 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:400:30)\n(elided 31 frames from class _FakeAsync, class _RawReceivePortImpl, class _Timer, dart:async, dart:async-patch, and package:stack_trace)\n\nThis was caught by the test expectation on the following line:\n file:///Users/home/Projetos/casacivil/ta_na_lei/test/ui/screens/legislacao/legislacao_screen_test.dart line 49\nThe test description was:\n exibe lista de legislacao quando legislacoes carregadas\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:04 +2 -1: LegislacaoScreen exibe lista de legislacao quando legislacoes carregadas [E] \n Test failed. See exception logs above.\n The test description was: exibe lista de legislacao quando legislacoes carregadas\n\n00:04 +3 -1: Some tests failed. \nRun Code Online (Sandbox Code Playgroud)\n\n编辑2:
\n\n在我阅读这篇文章https://medium.com/flutter/event-loop-in-widget-tester-50b3ca5e9fc5后,问题似乎出在异步环境上。我尝试在 runAsync 方法中调用我的测试,但它不起作用,然后我添加了 wait Future.delayed(Duration(seconds: 5)) 并且它起作用了。由于某种原因,读取文件需要很长时间(在其他测试中读取速度非常快)。一件有趣的事情是,具有持续时间的泵不会延迟测试......
\n\n嗯,现在可以使用此解决方法,但我想知道解决该问题的正确方法。
\n\nawait tester.runAsync(() async {\n await tester.pumpWidget(buildWidget());\n await Future.delayed(Duration(seconds: 5));\n\n await tester.pump(Duration(seconds: 2));\n\n expect(find.byType(LegislacaoLista), findsOneWidget);\n });\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1091 次 |
| 最近记录: |