Flutter 在带有颤振的单元测试期间,对文件对象的操作从未完成
我正在为我的flatter应用程序编写单元测试,在读取json文件时遇到了一些问题。我的api模拟类使用了一些json文件。每当我调用File对象上的方法时,它永远不会结束,但测试会继续执行,并以错误结束,因为它没有从File对象接收数据。这是非常奇怪的,因为它只发生在从一个小部件调用的提供者调用mockapi方法时。如果我在测试中直接调用mock-api方法,它可以正常工作。 我的应用程序的结构如下:WidgetScreen调用->提供者调用->mockApi Widget Legislacao屏幕从我的提供者调用方法carregarLegislacao,该方法从我的mockApi调用方法getLegislacoes,该方法读取json文件并将结果返回给提供者,提供者随后通知我的Widget。感谢您的帮助 哦,我正在用命令运行我的测试:flattertest test/my_test.dart 下面是一些代码: 屏幕显示:Flutter 在带有颤振的单元测试期间,对文件对象的操作从未完成,flutter,dart,flutter-test,dart-io,Flutter,Dart,Flutter Test,Dart Io,我正在为我的flatter应用程序编写单元测试,在读取json文件时遇到了一些问题。我的api模拟类使用了一些json文件。每当我调用File对象上的方法时,它永远不会结束,但测试会继续执行,并以错误结束,因为它没有从File对象接收数据。这是非常奇怪的,因为它只发生在从一个小部件调用的提供者调用mockapi方法时。如果我在测试中直接调用mock-api方法,它可以正常工作。 我的应用程序的结构如下:WidgetScreen调用->提供者调用->mockApi Widget Legislaca
class LegislacaoScreen extends StatefulWidget {
@override
_LegislacaoScreenState createState() => _LegislacaoScreenState();
}
class _LegislacaoScreenState extends State<LegislacaoScreen>
with AutomaticKeepAliveClientMixin {
@override
void initState() {
super.initState();
Future.microtask(carregarDados);
}
@override
bool get wantKeepAlive => true;
Future<void> carregarDados({bool reset = false}) async {
try {
final legislacaoProvider =
Provider.of<LegislacaoProvider>(context, listen: false);
await legislacaoProvider.carregarLegislacao(
page: legislacaoProvider.currentPage + 1,
reset: reset,
);
} catch (err) {}
}
Widget renderBody(legislacaoProvider) {
if (legislacaoProvider.carregandoLegislacao &&
legislacaoProvider.legislacoes.isEmpty &&
!legislacaoProvider.reseting) {
return Center(
child: CircularProgressIndicator(),
);
}
if (legislacaoProvider.erroCarregandoLegislacao) {
return MensagemAcao(
mensagem:
'Houve um erro ao carregar os dados.\nPor favor tente novamente.',
acao: () => carregarDados(reset: true),
);
}
return LegislacaoLista(
carregandoLegislacao: legislacaoProvider.carregandoLegislacao,
legislacoes: legislacaoProvider.legislacoes,
reseting: legislacaoProvider.reseting,
carregarDados: carregarDados,
isFiltroEmpty: legislacaoProvider.isFiltroEmpty,
);
}
@override
Widget build(BuildContext context) {
super.build(context);
final legislacaoProvider = Provider.of<LegislacaoProvider>(context);
return Scaffold(
appBar: CustomAppBar(
title: 'Legislação',
actions: <Widget>[
IconButton(
icon: Icon(
Icons.search,
color: legislacaoProvider.isFiltroEmpty
? Colors.white
: CustomColors.verde2,
),
onPressed: () {
Navigator.of(context)
.pushNamed(PesquisarLegislacaoScreen.routeName);
},
),
],
),
backgroundColor: Colors.white,
body: renderBody(legislacaoProvider),
);
}
class LegislacaoProvider with ChangeNotifier {
bool _carregandoLegislacao = true;
bool _erroCarregandoLegislacao = false;
List<Legislacao> legislacoes = [];
int currentPage = 0;
bool _reseting = false;
LegislacaoApi _legislacaoApi;
LegislacaoProvider({LegislacaoApi legislacaoApi})
: _legislacaoApi = legislacaoApi ?? LegislacaoApiService();
bool get carregandoLegislacao {
return _carregandoLegislacao;
}
bool get erroCarregandoLegislacao {
return _erroCarregandoLegislacao;
}
bool get reseting {
return _reseting;
}
Future<void> carregarLegislacao({
int page = 1,
bool reset = false,
}) async {
try {
_carregandoLegislacao = true;
_erroCarregandoLegislacao = false;
_reseting = reset;
if (reset) {
page = 1;
}
notifyListeners();
legislacoes = await _legislacaoApi.getLegislacoes(
page: page,
ementa: filtro['ementa'],
conteudo: filtro['conteudo'],
ano: filtro['ano'],
periodoInicialLegislacao: filtro['periodoInicialLegislacao'],
periodoFinalLegislacao: filtro['periodoFinalLegislacao'],
tipoLegislacao: filtro['tipoLegislacao']?.id,
numero: filtro['numero'],
autor: filtro['autor'],
);
_carregandoLegislacao = false;
_reseting = false;
notifyListeners();
} catch (err) {
print(err);
_erroCarregandoLegislacao = true;
_carregandoLegislacao = false;
_reseting = false;
notifyListeners();
throw TaNaLeiException(err.toString());
}
}
}
class LegislacaoApiServiceMock extends LegislacaoApi {
bool _fail = false;
LegislacaoApiServiceMock();
LegislacaoApiServiceMock.fail() : _fail = true;
@override
Future<List<Legislacao>> getLegislacoes({
int page = 1,
String conteudo,
String ementa,
String ano,
DateTime periodoInicialLegislacao,
DateTime periodoFinalLegislacao,
int tipoLegislacao,
String numero,
String autor,
}) async {
if (_fail) {
throw Error();
}
final file = File('test/data/get_legislacoes.json');
print('step 1');
final json = await file.readAsString();
print('step 2 '); // <-- NEVER GETS PRINTED
return jsonDecode(json)
.map<Legislacao>(
(elemento) => Legislacao.fromJson(elemento),
)
.toList();
}
}
final locator = GetIt.instance;
void setupLocatorLegislacaoProvider({LegislacaoApi legislacaoApi}) {
locator.registerLazySingleton<LegislacaoProvider>(() => LegislacaoProvider(
legislacaoApi: legislacaoApi,
));
}
void main() async {
TestWidgetsFlutterBinding.ensureInitialized();
setupLocatorLegislacaoProvider(legislacaoApi: LegislacaoApiServiceMock());
group('LegislacaoScreen', () {
Widget buildWidget() {
return ChangeNotifierProvider.value(
value: locator<LegislacaoProvider>();,
child: MaterialApp(
home: LegislacaoScreen(),
routes: routes,
),
);
}
testWidgets('builds screen', (WidgetTester tester) async {
final child = buildWidget();
await tester.pumpWidget(child);
expect(find.byWidget(child), findsOneWidget);
});
testWidgets('finds list when data is loaded',
(WidgetTester tester) async {
await tester.pumpWidget(buildWidget());
await tester.pump();
await tester.pump();
expect(find.byType(LegislacaoLista), findsOneWidget);
});
});
}
是否有其他服务或应用程序正在写入该文件?比如可能会导致锁死的东西。另外,请张贴在结尾处收到的错误消息。@dev aentgs不允许其他服务访问该文件。问题:我应该在执行readAsString后关闭文件吗?我没有在示例中看到它。没有提到接近。我想它是在内部处理的。@dev aentgs我设法用一种变通方法来运行测试。我编辑了这篇文章。好:)。测试框架中可能存在问题。是否有其他服务或应用程序正在写入该文件?比如可能会导致锁死的东西。另外,请张贴在结尾处收到的错误消息。@dev aentgs不允许其他服务访问该文件。问题:我应该在执行readAsString后关闭文件吗?我没有在示例中看到它。没有提到接近。我想它是在内部处理的。@dev aentgs我设法用一种变通方法来运行测试。我编辑了这篇文章。好:)。可能是测试框架中的问题。
➜ ta_na_lei git:(testes) ✗ flutter test test/ui/screens/legislacao/legislacao_screen_test.dart
00:03 +0: LegislacaoScreen builds screen
dentro de mock 1
00:04 +1: LegislacaoScreen exibe circular progress indicator quando carregando legislacao e reset true
dentro de mock 1
00:04 +2: LegislacaoScreen exibe lista de legislacao quando legislacoes carregadas
dentro de mock 1
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _WidgetTypeFinder:<zero widgets with type "LegislacaoLista" (ignoring offstage widgets)>
Which: means none were found but one was expected
When the exception was thrown, this was the stack:
#4 main.<anonymous closure>.<anonymous closure> (file:///Users/home/Projetos/casacivil/ta_na_lei/test/ui/screens/legislacao/legislacao_screen_test.dart:49:7)
<asynchronous suspension>
#5 main.<anonymous closure>.<anonymous closure> (file:///Users/home/Projetos/casacivil/ta_na_lei/test/ui/screens/legislacao/legislacao_screen_test.dart)
#6 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#7 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#8 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:703:19)
<asynchronous suspension>
#11 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:683:14)
#12 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1083:24)
#18 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1080:15)
#19 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#20 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:172:27)
<asynchronous suspension>
#21 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)
#22 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:246:15)
#27 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:243:5)
#28 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:170:33)
#33 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:13)
#34 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:400:30)
(elided 31 frames from class _FakeAsync, class _RawReceivePortImpl, class _Timer, dart:async, dart:async-patch, and package:stack_trace)
This was caught by the test expectation on the following line:
file:///Users/home/Projetos/casacivil/ta_na_lei/test/ui/screens/legislacao/legislacao_screen_test.dart line 49
The test description was:
exibe lista de legislacao quando legislacoes carregadas
════════════════════════════════════════════════════════════════════════════════════════════════════
00:04 +2 -1: LegislacaoScreen exibe lista de legislacao quando legislacoes carregadas [E]
Test failed. See exception logs above.
The test description was: exibe lista de legislacao quando legislacoes carregadas
00:04 +3 -1: Some tests failed.
await tester.runAsync(() async {
await tester.pumpWidget(buildWidget());
await Future.delayed(Duration(seconds: 5));
await tester.pump(Duration(seconds: 2));
expect(find.byType(LegislacaoLista), findsOneWidget);
});