Playground

Flutter でユニットテストを作っていたら rootBundle.loadString の mock で沼った話

Playground
この記事は約5分で読めます。
スポンサーリンク

お久しぶりです。みやかわです。

Flutter でユニットテストをゴリゴリ書いています。

初めて Flutter でユニットテストを書いているのですがわからないことが多く、グーグル先生に頼りっぱなしです。

さて、rootBundle.loadString のユニットテストを書いていたのですが沼ってしまいました。

なんとか解決できたので、解決方法を記事にしていきます。

スポンサーリンク

実装環境

  • OS
    macOS Monterey 12.0.1(21A559)
  • Flutter
    Flutter 2.10.3

    Dart 2.16.1 • DevTools 2.9.2

そもそも rootBundle.loadString とは

rootBundle.loadString について触れていませんでした。

これを使うことで Flutter で Assets フォルダにアクセスすることができます。

詳細は、APIドキュメントを参照してください。

rootBundle property - services library - Dart API
API docs for the rootBundle property from the services library, for the Dart programming language.

ユニットテストを書く

テスト対象

Assetsフォルダ内にあるファイルを読むこむClassをテスト対象にします。

この中にある rootBundle.loadString をmock したいとします。

class TemplateShareFile {
  dynamic fetchTemplateShareFile(String file) async {
    const path = Common.postTemplateFolder;

    try {
      final res = await rootBundle.loadString('$path/$file');
      return res;
    } catch (e) {
      debugPrint('err $e');
      return 'err';
    }
  }
}

テストする

Assetsにあるフォルダ内にあるファイルを読むことに成功するかのテストを書いておきます。

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  group('fetchTemplateShareFile', () {
    setUp(() {
      ServicesBinding.instance!.defaultBinaryMessenger
          .setMockMessageHandler('flutter/assets', (_) {
        final Uint8List encoded = utf8.encoder.convert('mock');
        return Future.value(encoded.buffer.asByteData());
      });
    });

    test('ローカルファイルを読むことに成功する', () async {
      final templateShareFile = TemplateShareFile();
      final dynamic res =
          await templateShareFile.fetchTemplateShareFile('mock');
      expect(res, 'mock');
    });
  });
}

TestWidgetsFlutterBinding.ensureInitialized(); をテストを行う前に、つけることがポイントです。

これをしないと以下のようなエラーがでます。

Null check operator used on a null value
test/local_clinet_test.dart 15:31  main..

その他

ググっていたら、rootBundle を mock してテストしているコードを見つけました。

この方法で解決することができました。

packages/flutter/test/services/platform_messages_test.dart - external/github.com/flutter/flutter - Git at Google

 

また、あとから調べてわかったのですが Flutter 1.9.4 から rootBundle を mock するときは、TestWidgetsFlutterBinding.ensureInitialized() を使うのが必須になったようです。

 

コメント

タイトルとURLをコピーしました