⛳
[Flutter] Riverpod(hooks_riverpod)でWidget Test時にProviderを上書きする書き方のサンプル
☆初めての記事投稿になります。間違い等ありましたらご指摘のほどよろしくお願い致します☆
環境
- Dart: 2.12.0
- Flutter: 1.26.0-17.5.pre
- hooks_riverpod: 0.12.4
- freezed: 0.12.7
この記事の目的
公式DocsのTestingページには1つのdartファイルでWidget定義とTestを行っている例が書いてありますが、一般的には別ファイルで書くことが多いはずです。
Riverpodではテスト時にProviderの実装を書き換えることができます。自分でWidget Testを書いてる際に勘違いをしてTestが通らず考え込んでしまったので、備忘録として書いておきます。
自分のしていた勘違い
Widget Test時にはTestを書いたのと同じdartファイル内で定義したProviderが呼ばれると思っていましたが、呼ばれるのはあくまでもuseProvider
等で呼び出しているProviderです。[1]
Widget定義とTestを別に書くサンプル
ここからは、サンプルコードを書いておきます。参考になれば幸いです。
state/auth/user/auth_state.dart
abstract class AuthState with _$AuthState {
const factory AuthState({
(false) bool isAuthenticated
}) = _AuthState;
}
class AuthStateNotifier extends StateNotifier<AuthState> {
AuthStateNotifier() : super(const AuthState());
AuthStateNotifier.withDefaultValue({ bool isAuthenticated})
: super(AuthState(isAuthenticated: isAuthenticated));
set isAuthenticated(bool authenticationState) {
state = state.copyWith(isAuthenticated: authenticationState);
}
bool get isAuthenticated {
return state.isAuthenticated;
}
}
lib/middleware/auth_middleware.dart
final authStateNotifierProvider =
StateNotifierProvider((_) => AuthStateNotifier());
class AuthMiddleWare extends HookWidget {
const AuthMiddleWare(this.amplifyApi);
final AmplifyApiInterface amplifyApi;
Widget build(BuildContext context) {
final authStateNotifier = useProvider(authStateNotifierProvider);
if (authStateNotifier.isAuthenticated) {
return HomeView();
} else {
return StartupView();
}
}
}
Test codeはこんな感じ。
test/widget/middleware/auth_middleware_test.dart
void main() {
group('AuthMiddleware', () {
testWidgets('should go to HomeView Page when authenticated',
(WidgetTester tester) async {
await tester.pumpWidget(
ProviderScope(
// ここでProviderの実装を上書き。authStateNotifierProviderを呼ぶことに注意。
overrides: [
authStateNotifierProvider.overrideWithValue(
AuthStateNotifier.withDefaultValue(isAuthenticated: true),
),
],
child: MaterialApp(
home: AuthMiddleWare(),
),
),
);
expect(find.byType(HomeView), findsOneWidget);
});
});
}
-
よく考えれば当たり前のことでした... ↩︎
Discussion