Home > Back-end >  Flutter Widget Test: cannot find widget using find.byWidget()
Flutter Widget Test: cannot find widget using find.byWidget()

Time:11-22

I was following this example to test if a CircularProgressIndicator is present in my view, but even though the Flutter build tree shows the widget is present, I keep getting the following exception:

══╡ 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
════════════════════════════════════════════════════════════════════════════════════════════════════

Edit

I've made a method that builds a MaterialApp with just a CircularProgressIndicator Widget as its "child":

Widget createMockViewRequest() {
  return MaterialApp(
      title: 'SmartDevice Simulator',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const CircularProgressIndicator());
}

And the following test still keeps failing with the same exception:

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();
});

Am I doing something wrong? Maybe the MaterialApp doesn't count as a container? But in that case I fail to understand why it should not.

CodePudding user response:

You have to change your example like this:

 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);
  });

or like this:

 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);
  });

Please note, that I remove await tester.pumpAndSettle(); because it waits when the animation completes on your page, but CircularProgressIndicator will spin to infinity so that you will have a timeout exception.

CodePudding user response:

There are a few things to change in order to make it work.

First of all, if you use await tester.pumpAndSettle() while testing a widget with an infinite animation such as a CircularProgressIndicator, the test will fail because it is waiting for the last frame to be updated but the animation never ends, therefore a timeout is thrown.

Apart from that, your test is failing because of the finder that you are using, you are trying to find the very same instance that you are providing to the expect in your UI, and this is not the case, since the instance that gets built in the UI is different from the one that you are creating inside your test, in this case, if you want to check if there is a CircularProgressIndicator on the UI, you should use the find.byType finder, which searches for a Widget of the provided type in the widget that has been built.

  • Related