お久しぶりです。みやかわです。
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ドキュメントを参照してください。
ユニットテストを書く
テスト対象
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 してテストしているコードを見つけました。
この方法で解決することができました。
また、あとから調べてわかったのですが Flutter 1.9.4 から rootBundle を mock するときは、TestWidgetsFlutterBinding.ensureInitialized() を使うのが必須になったようです。