DEV Community

Cover image for Flutter: Data Testing
Reme Le Hane
Reme Le Hane

Posted on • Originally published at remelehane.dev

Flutter: Data Testing

In a previous post, we discussed using find.byPredicate for more accurate and bulletproof widget testing.

Flutter: Up your testing game

In this post we are going to quickly go through that same logic, but for data related unit testing.

For the 95% of my data models, I would use freezed, a wonderful package that makes one life a lot simpler when it comes to data classes, including adding in a few utility methods as well as simplifying unit testing by handling equality, something I previously achieved manually and with some help from equatable.

However, there is a bit of boilerplate when using freezed as it works with code generation.

enum MenuItemKey {logout, dashboard}

class MenuItem {
  final MenuItemKey key;
  final String localeKey;
  final PageRouteInfo route;

  MenuItem({
    required this.key,
    required this.localeKey,
    required this.route,
  });

  static List<MenuItem> menuItems = [...]

  static List<MenuItem> itemsToDisplay(List<MenuItemKey> excludedKeys) {
    return menuItems
        .where((element) => !excludedKeys.contains(element.key))
        .toList();
  }
}
Enter fullscreen mode Exit fullscreen mode

Take this class, for example, adding in freezed would have been straightforward, add 2 or 3 lines of code and an extra generated file, however to me it felt unnecessary as this is a model I created for simply managing a navigation list, there is no data to test, no relation to an API, no need for equality or the utility methods, etc.

There is a menu in my application, which gets provided the menuItems list and with that, I generate the nav items.

However, I do still want to be able to accurately test itemsToDisplay, the 1 bit of logic attached to this class, by default all items are based on the generation function, however not all screens have all the nav items. The login screen would have no need for the Logout button for example.

The Test...

As with widgets, we can use predicate as part of our expect function, to drill down into data models and compare results with defined values.

  test('should return only logout menu item', () async {
    //act
    final result = MenuItem.itemsToDisplay([
      MenuItemKey.dashboard,
      MenuItemKey.support,
      MenuItemKey.profile,
    ]);
    //assert
    expect(
      result,
      predicate(
        (List<MenuItem> items) =>
            items.length == 1 && items.first.key == MenuItemKey.logout,
      ),
    );
  });
Enter fullscreen mode Exit fullscreen mode

In the above example, we would have had 4 items in the menuItems list and made the decision to filter out all BUT logout.

In order to verify our function is working then, we use predicate which takes a function as an expectation, to which we have the data type we are expecting and then return a check which yields a boolean result.

In this case, we had a list that contained 4 menu items, we excluded 3 of them so we verify that our list only has 1 item in it, and to make sure the correct item remains, we verify that the first (only) item in the list has the key of MenuItemKey.logout, which is the enum value assigned to the navigation item.

Conclusion...

As you can now see, find.byPredicate and predicate are 2 very useful methods that we as testers should keep in mind when writing out tests. They can help with less-standard use cases and allow us to write a higher-quality test.


I hope you found this interesting, and if you have any questions, comments, or improvements, feel free to drop a comment. Enjoy your Flutter development journey :D

If you enjoyed it, a like would be awesome.

Thanks for reading.


Wish to carry on with the topic of Unit Testing, take a look at:

Top comments (0)