简体   繁体   中英

Flutter Widget Test Doesn't Find Created Widget

I have 2 options to change view of datas presenting on screen.

  • 1 is ListView
  • 2 is GridView There are two icons to change view:

在此处输入图像描述

Here is the code of icons above:

Padding changeView() {
return Padding(
  padding: const EdgeInsets.only(right: 15.0),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.end,
    children: [
      Padding(
        padding: const EdgeInsets.all(5.0),
        child: GestureDetector(
          key: const Key("listViewIcon"),
          child: const Icon(conf.listView),
          onTap: () => setState(() {
            _isListView = true;
          }),
        ),
      ),
      Padding(
        padding: const EdgeInsets.all(5.0),
        child: GestureDetector(
          key: const Key("gridViewIcon"),
          child: const Icon(conf.gridView),
          onTap: () => setState(() {
            _isListView = false;
          }),
        ),
      ),
    ],
  ),
);

}

When I tap on the icons _isListView property set. According to this property i build grid view or listview:

Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBar(
    title: Text(widget.title),
  ),
  body: Column(
    children: [
      //search and filter
      searchAndFilter(context),
      const Divider(),
      //listview or gridview
      changeView(),
      //objects table
      _isListView ? listView(TEST.objects()) : gridView(TEST.objects()),
    ],
  ),
);

}

But I cant test this operation, my test code is below:

void main() {
  List<ObjectView> objects = [];
  ObjectView o1 = ObjectView();
  o1.image = const AssetImage('assets/avatar.jpeg');
  o1.title = "TITLE";
  o1.payload = "test";
  objects.add(o1);
  testWidgets("View Change Test", (WidgetTester tester) async {
  //related widgets
  final listViewIcon = find.byKey(const Key("listViewIcon"));
  final gridViewIcon = find.byKey(const Key("gridViewIcon"));

  await tester.pumpWidget(
    const MaterialApp(
      home: HomePage(title: conf.appName),
    ),
  );
  await tester.tap(listViewIcon);
  await tester.pump();

  expect(find.byWidget(ListViewScroll(objects: objects)), findsOneWidget);
});

}

When I click icons ListViewScroll or GridViewScroll widgets should be built. Bu the error says:

在此处输入图像描述

ListViewScroll Widget:

class ListViewScroll extends StatelessWidget {
  const ListViewScroll({
    Key? key,
   required this.objects,
  }) : super(key: key);

  final List<ObjectView> objects;

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: objects.length,
      itemBuilder: (BuildContext context, int index) {
        return SizedBox(
          height: conf.listTileHeight,
          child: Card(
            child: Center(
              child: ListTile(
                leading: Image(
                  image: objects.elementAt(index).image!,
                ),
                title: Text(objects.elementAt(index).title!),
                subtitle: Text(objects.elementAt(index).payload!),
              ),
            ),
          ),
        );
      },
    );
  }
}

Any ideas? Thanks.

Flutter always finds needed stuff that is present on the screen. There are several possible reasons why it can't find something:

  1. It is not rendered yet. (you would have to pump till it is)
  2. It is not visible on the screen - for example, the last element of the long list(you would have to scroll down till it is visible)
  3. The condition is not correct - you try to find something by giving the finder incorrect data. (I think it is the issue in your case - if previous aren't)

You are trying to find an element byWidget that contains a list of objects. There are several reasons it may fail(now I only presume):

  1. The data you provided to the finder is not the same as the one present in the actual widget. In this case, you should check the correctness of the data
  2. The finder may be looking by the link and not by the value(I don't know for sure - I just assume in this case) - thus two identical lists will not be equal because of different links and actual lists in memory. In this case, you should compare something that is compared by the value for sure - as strings or primitives. Also, you can try to use other ways of finding you widget, for example, I like to use byWidgetPredicate:
 expect(
            find.byWidgetPredicate(
              (widget) =>
                  widget is ListViewScroll &&
                  widget.objects.isNotEmpty &&
                  widget.objects[0].title == "TITLE", //... - you can add more checks
            ),
            findsOneWidget);
// This way you will be able to fully control all the checks and be sure what is compared

Either way, the flutter test always finds stuff - if it doesn't that means that the issue is one(or several) of the above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM