Flutter-flutter_backgroundのUnitTest用の実装

Flutterのバックグラウンドサービスとしてflutter_backgroundを使おうとしたのだけど、書いたサービスをWindows環境でUnittestがしづらかったのでasync版、isolate版を実装してみた。

flutter_background | Flutter package
Run apps in the background using foreground services on Android. Ideal for applications that require continuous operatio...

初めに

本来のテストはどうするべきなのか上のgithub上のtestを見たのだけど、テスト自体の記述がなかった。

次にMockを作ってみたのだけど、Mock用のコードを書く方がかなり難易度が高く断念した。
基点となるMock対応するクラスはServiceInstanceなんだけど、データのやり取りのためにPort(Stream)を使っていて、listenのMockを作るのが大変だった。

そこで、Windows(デスクトップ版)でも動作可能なようにまずはIsolate版、次にAsync版の実装を作り、それを利用してテストをすることにした。
これにより通常の関数呼び出しを行う形でテストを行うことができた。

Isolate版

flutter_backgroundのisolate実装版
flutter_backgroundのisolate実装版. GitHub Gist: instantly share code, notes, and snippets.

ServiceInstanceとFlutterBackgroundServicePlatformの派生を作成し、データのやり取りに関してはReceivePort()経由で行うような実装にしている。

Async版

Isolate版を作成した後、バックグラウンドで動かすためのデータをshared_preferences経由でやり取りすることにしたため、テストではIsolate版が使えなくなったためAsync版を作ることにした。

これはFlutter-テスト時のSharedPreferences取扱い注意点に関連した話。

flutter_backgroundのasync実装版
flutter_backgroundのasync実装版. GitHub Gist: instantly share code, notes, and snippets.

Async版はIsolate版を単純にAsyncに変更しただけ。

Isolate版または標準の実装と異なるのは、stopSelf()で完全停止ができないという点。
なんとなく停止させているだけになっている。

テストでの使用方法

実際のテストではAsync版を使うことになったのだけど、Async版ではコンテキストスイッチをさせるために、テスト内で適時await Future.delayed(const Duration(milliseconds: 100));を呼び出してバックグラウンド側の関数を動かす必要がある。

待機時間は100msとしているが、サーバー側の処理でawaitを使っている箇所があると、長めに設定する必要がある。逆にサーバー側でawait含め処理時間が短い場合はμ秒あたりの設定値でも問題はなかった。

コンテキストスイッチに関してはDart-Async/Awaitをちょっと調査を参照。

コメント

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