state_notifierとfreezedのプロジェクトでMockitoを用いたunit test

エキサイト株式会社の高野です。
弊社では最近Flutterでテストを書き始めました。state_notifierとfreezedを用いたプロジェクトをどうやってテストしようか考えていた所Mockitoを見つけ、よさそうでしたので書いてみたコードの流れの紹介になります。

各バージョン

Flutter: 2.0.6
iOS: 14.5
Android: 11.0

使用ライブラリ

mockito

実装

僕が今開発しているローリエプレスにおける最も重要たるロジックはAPIから受け取ったものをView側に流してあげることです。
プロジェクト自体は、state_notifierとfreezedを用いて実装していますのでrepositoryから受け取ったものをstateに渡せているかをテストしていきます。

@GenerateMocks([RepositoryImpl])
void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  final _mockRepositoryImpl = MockRepositoryImpl();
  final controller = Controller(
      controller: controller,
   );
}

以上のようにRepositoryをMockitoを用いてモック化し、Controllerをイニシャライズします。

test('記事を20件取得する', () async {
      when(RepositoryImpl.fetchArticleList(category: Pickup().package, page: 1, size: 20))
          .thenAnswer((_) async =>
          Result.success(List.generate(20, (_) => Article())));
      await controller.initArticleList();
      expect(controller.state.maybeMap(
          success: (s) => s.articles.length,
          orElse: () {},
      ), 20);
      expect(pickupArticleListController.page, 1);
    });

つづいて以上のようにrepositoryのメソッドに必要な引数を設定し、Futureメソッドですので thenAnswer を用いて返り値を指定してあげます。今回ですとArticle型のListを要素20で生成しました。
その後メソッドを実行し、stateのarticlesの長さが20に変更されているかを確認します。
僕のプロジェクトですと、stateをsuccess, loading, errorの3つの状態で用意していますので今回はAPIがうまくいっているものを前提としているのでsuccessに通ってくるのでmaybeMapを使用しています。

まとめ

Futureメソッドで返り値がResultかつそれをstate.copyWithで変数を変更した場合のUnitTestの紹介でした。これを元に他のファイルもテストしていこうと思います。

www.wantedly.com