Testing
中規模から大規模のアプリケーションでは、アプリケーションをテストすることが重要です。
アプリケーションのテストを成功させるためには、以下のものが必要です。
test
/testWidgets
の間では、状態を保存してはいけません。
これは、グローバルな状態がない、またはすべてのグローバルな状態が各テストの後にリセットされるべきであることを意味します。モックを使ったり、目的の状態になるまで操作したりして、
プロバイダに特定の状態を強制することができます。
Riverpodがこれらをどのようにサポートするのか、一つずつ見ていきましょう。
test
/testWidgets
の間では、状態を保存してはいけません#
プロバイダは通常、グローバル変数として宣言されているので、その点は心配ないでしょう。
結局のところ、グローバルステートはテストを非常に難しくしています。
なぜならば、長い setUp
/tearDown
が必要になるからです。
しかし、現実には、プロバイダはグローバルに宣言されていますが、プロバイダの状態はグローバルではありません。
その代わりに、ProviderContainerというオブジェクトに格納されています。
このオブジェクトは、Dartのみの例をご覧になった方はご存知かもしれません。
まだご覧になっていない方は、このProviderContainerオブジェクトは、
私たちのプロジェクトでRiverpodを有効にするウィジェットである、
ProviderScopeによって暗黙のうちに作成されていることを知っておいてください。
具体的には、プロバイダを利用している2つのtestWidgets
は、状態を共有しないということです。
そのため、SetUp
/ TearDown
は一切必要ありません。
長々とした説明よりも、例えがあった方がいいですね。
- testWidgets (Flutter)
- test (Dart only)
ご覧のとおり、counterProvider
はグローバルとして宣言されていますが、テスト間で状態は共有されていません。
このように、テストは完全に分離して実行されるため、
異なる順序で実行された場合にテストの動作が異なる可能性があることを心配する必要はありません。
#
テスト時にProviderの動作をオーバーライドする。一般的なアプリケーションでは、次のようなオブジェクトがあります。
Repository
クラスは、HTTPリクエストを実行するための型安全でシンプルなAPIを提供します。アプリケーションの状態を管理するオブジェクトで、
Repository
を使用してさまざまな要因に基づいてHTTPリクエストを実行することがあります。 これは、ChangeNotifier
やBloc
、あるいはProviderかもしれません。
Riverpodを使って、これを次のように表すことができます。
このような状況で、ユニットテストやウィジェットテストを行う際には、
通常、Repository
のインスタンスを、実際のHTTPリクエストの代わりに、
あらかじめ定義されたレスポンスを返す偽の実装に置き換えたいと思うでしょう。
次に、todoListProvider
(またはそれに相当するもの)がRepository
のモックされた実装を使用するようにします。
これを実現するには、ProviderScope/ProviderContainerのoverrides
パラメータを使用して、
repositoryProvider
の動作をオーバーライドします。
- ProviderScope (Flutter)
- ProviderContainer (Dart only)
ハイライトされたコードを見ればわかるように、ProviderScope/ProviderContainerは、
プロバイダの実装を別の動作に置き換えることができます。
info
一部のプロバイダーは、その動作をオーバーライドするための簡易な方法を公開しています。
例えば、FutureProviderでは、AsyncValue
でプロバイダをオーバーライドすることができます。
#
完全なウィジェットのテスト例最後に、今回のFlutterテストの全コードを紹介します。