FlutterのTestでCallbackをmockitoでモックする
FlutterのテストでChangeNotifierのサブクラスのaddListenerに渡したCallbackが呼ばれたかテストしたい場合に、ダミーのコールバックでフラグを立ててフラグをexpectで検査することがある。
これをmockitoを使ってverifyで検証する方法がある。
返値がVoidのモック
まず以下のmixin(もしくはclassでも可)を作成する。
mixin Callback {
T call();
}
callメソッドを持ったクラスは関数のようにcallメソッドを呼ぶことができるようになる。例えば以下のように。
class A {
void call() { print('a'); }
}
final a = A();
a(); // a.call()が実行されaが出力される
次にmockitoのGenerateMocksアノテーションで、CallbackからCallbackのモックを作成する。以下を記述してbuild_runner
buildを実行する
Widget TestでGoRouterのモックを利用するにはInheritedGoRouter
WidegtをWidgetツリーに組み込むと良いのですが、GoRouterライブラリではInheritedGoRouterはexportされておらず、利用できませんでした。
ということでFlutter PackagesのIssueとPRを作成してGoRouterに取り込んでもらいました。
すでにリリースされているので、Widget Testでは以下のようにGoRouterのモックを組み込むことができます。
testWidgets('mediates Widget\'s access to GoRouter.',
(WidgetTester tester) async {
final MockGoRouter router = MockGoRouter();
await tester.pumpWidget(MaterialApp(
home: InheritedGoRouter(goRouter: router,
この記事では宣言的UIにどのアーキテクチャパターンが良いかを述べるのではなく、宣言的UIでのアーキテクチャパターンの課題とアドバイスを記しています。
概論
私はiOSネイティブアプリのプログラマでした。現在でも個人ではSwiftUIでアプリを作成していますが、業務ではFlutterアプリを作成しています。ですのでAndroidネイティブのことはわからないのでiOSとFlutterを主に話題にします。
iOSのUIKitではMVCが標準のアーキテクチャパターンでした。一方SwiftUIやFlutterは標準のアーキテクチャパターンが存在しません。存在しないとどうなるのでしょうか。去年私が引き継いだFlutterプロジェクトが、存在しない場合の最悪な実装を示してくれました。
簡単に述べると「WidgetがAPIアクセスを行い、JSONから子Widgetが生成され表示する」という実装です。当然Widgetは肥大化してスパゲッティコードになっていました。
UIKitではMVCのCが肥大化する問題が注目されていますが、標準アーキテクチャパターンが存在することで少なくともVとCは分離され、
iOS Simulatorの操作中にVSCodeにショートカットキーを送る FlutterアプリをiOS Simulatorで操作中にHot
Restartなどを行うにはVisual Studio Codeをアクティブにして操作する必要がある。
iOS Simulatorがアクティブな状態でHot Restartを行うにはVSCodeにキーイベントを送信すると可能になる。
Keyboard Maestro [https://www.keyboardmaestro.com/main/]を使うと簡単に仕組みを作ることができる。
1. Keyboard Maestroのマクログループを作成
2. 作成したグループにAvailable in these applicationsとしてSimulatorをセット
3. グループ内にマクロを作成
4. Hot Key Trigger(もしくは何らかのTrigger)
FlutterのAmplifyでS3にファイルをアップロードするとフォルダにPrefixをつけられてしまう FlutterでAWS
S3にファイルをアップロードするためにprachiFam/amazon_s3_cognito
[https://github.com/prachiFam/amazon_s3_cognito]というライブラリを利用していた。
しかしこのライブラリでは最新のFlutterでAndroid向けにビルドできない問題があり、AWSの公式ライブラリである
aws-amplify/amplify-flutter [https://github.com/aws-amplify/amplify-flutter]
に乗り換えようとした。
amplifyコマンドでauthとstorageをimport。amplifyライブラリを組み込みセットアップを完了。アップロードは成功した。しかしサービスのサーバ側がファイルを認識しない。S3のbucketを開いてもファイルは無い…と思ったら実はpublic/アップロードで指定したkeyとしてファイルがアップロードされていた。