Я следовал этому примеру, чтобы проверить, присутствует ли CircularProgressIndicator
в моем представлении, но хотя дерево сборки Flutter показывает, что виджет присутствует, я продолжаю получать следующее исключение:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _WidgetFinder:<zero widgets with the given widget
(CircularProgressIndicator(<indeterminate>)) (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> (file:///D:/xxxx/xxxx/xxxx/test/widget_test/widget_test.dart:173:5)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)
This was caught by the test expectation on the following line:
file:///D:/xxxx/xxxx/xxxx/test/widget_test/widget_test.dart line 173
The test description was:
ViewRequest: Waiting Types List
════════════════════════════════════════════════════════════════════════════════════════════════════
Я создал метод, который создает MaterialApp
только с CircularProgressIndicator
виджетом в качестве «дочернего элемента»:
Widget createMockViewRequest() {
return MaterialApp(
title: 'SmartDevice Simulator',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const CircularProgressIndicator());
}
И следующий тест все еще продолжает терпеть неудачу с тем же исключением:
testWidgets('ViewRequest: Waiting Types List', (WidgetTester tester) async {
const childWidget = CircularProgressIndicator();
// Build our app and trigger a frame.
await tester.pumpWidget(createMockViewRequest());
// Verify that the page is loading until we receive the types.
expect(find.byWidget(childWidget), findsOneWidget);
await tester.pumpAndSettle();
});
Я делаю что-то неправильно? Может быть, MaterialApp
не считается контейнером? Но в таком случае я не понимаю, почему этого не должно быть.
Вы должны изменить свой пример следующим образом:
Widget createMockViewRequest(Widget widget) {
return MaterialApp(
title: 'SmartDevice Simulator',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: widget,
);
}
testWidgets('ViewRequest: Waiting Types List', (WidgetTester tester) async {
const childWidget = CircularProgressIndicator();
// Build our app and trigger a frame.
await tester.pumpWidget(createMockViewRequest(childWidget));
// Verify that the page is loading until we receive the types.
expect(find.byWidget(childWidget), findsOneWidget);
});
или вот так:
Widget createMockViewRequest() {
return MaterialApp(
title: 'SmartDevice Simulator',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const CircularProgressIndicator(),
);
}
testWidgets('ViewRequest: Waiting Types List', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(createMockViewRequest());
// Verify that the page is loading until we receive the types.
expect(find.byType(CircularProgressIndicator), findsOneWidget);
});
Обратите внимание, что я удаляю await tester.pumpAndSettle();
, потому что он ожидает завершения анимации на вашей странице, но CircularProgressIndicator будет вращаться до бесконечности, так что у вас будет исключение тайм-аута.
Есть несколько вещей, которые нужно изменить, чтобы заставить его работать.
Прежде всего, если вы используете await tester.pumpAndSettle()
при тестировании виджета с бесконечной анимацией, такой как CircularProgressIndicator
, тест завершится неудачно, потому что он ожидает обновления последнего кадра, но анимация никогда не заканчивается, поэтому выдается тайм-аут.
Кроме того, ваш тест терпит неудачу из-за того, что вы используете finder
, вы пытаетесь найти тот же самый экземпляр, который вы предоставляете для ожидания в своем пользовательском интерфейсе, и это не так, поскольку экземпляр, который создается в пользовательском интерфейсе отличается от того, который вы создаете в своем тесте, в этом случае, если вы хотите проверить, есть ли CircularProgressIndicator
в пользовательском интерфейсе, вы должны использовать средство поиска find.byType
, которое ищет виджет предоставленного типа в созданном виджете.
Большое спасибо за решение и объяснение. На самом деле причина, по которой я поставил метод
.pumpAndSettle()
, заключается в том, что у меня есть таймер, который заменяетCircularProgressIndicator
другим виджетом (имитирующим сбор необходимой информации), но все же я не знал, что анимацияCircularProgressIndicator
сделает приложение продолжайте загружать кадры. Чем больше ты знаешь :)