Riverpod-un testi: ProviderContainer və override
Riverpod-un test modeli iki elementə söykənir: konteyner və override.
ProviderContainer.test()— sənədə görə 3.0-da Riverpod-un bir hissəsidir: test üçün yeni konteyner yaradır və test bitəndə onu avtomatik sökür. Sənədin xəbərdarlığı birbaşadır: konteynerləri testlər arasında paylaşmayın; testin içindəProviderContainer-i birbaşa deyil,ProviderContainer.test()vasitəsilə istifadə edin.- `overrides` — istənilən provider əvəz oluna bilər, əlavə hazırlıq tələb olunmur:
ProviderContainer.test(overrides: [...])və ya widget testindəProviderScope(overrides: [...]).
Oxunuş üçün: container.read(provider) cari dəyəri verir; container.listen(provider, listener) isə dinləyici yaradır və avtomatik təmizlənmənin qarşısını alır — sənəd autoDispose provider-lərdə read-dən istifadə edərkən diqqətli olmağı və listen seçməyi tövsiyə edir. Async provider-in nəticəsini gözləmək üçün provider.future oxunur.
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
class FakeTodoRepository implements TodoRepository {
FakeTodoRepository(this.items);
final List<Todo> items;
@override
Future<List<Todo>> fetchAll() async => items;
}
void main() {
test('todosProvider repository-dən gələn siyahını qaytarır', () async {
final container = ProviderContainer.test(
overrides: [
// İstənilən provider override oluna bilər.
todoRepositoryProvider.overrideWithValue(
FakeTodoRepository([const Todo(id: '1', title: 'Süd al')]),
),
],
);
// Async provider-in nəticəsini future kimi gözləyirik.
await expectLater(
container.read(todosProvider.future),
completion(hasLength(1)),
);
});
test('add() siyahıya element əlavə edir', () async {
final container = ProviderContainer.test(
overrides: [
todoRepositoryProvider.overrideWithValue(FakeTodoRepository(const [])),
],
);
// listen: autoDispose provider-in test müddətində yaşamasını təmin edir.
final subscription = container.listen(todosProvider, (_, _) {});
await container.read(todosProvider.future);
await container.read(todosProvider.notifier).add('Yeni tapşırıq');
expect(subscription.read().value, hasLength(1));
});
}Unit test: konteyner, override və async nəticənin gözlənilməsi.
void main() {
testWidgets('siyahı boş olduqda boş vəziyyət göstərilir', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
todoRepositoryProvider.overrideWithValue(FakeTodoRepository(const [])),
],
child: const MaterialApp(home: TodoPage()),
),
);
// İlk frame: loading.
expect(find.byType(CircularProgressIndicator), findsOneWidget);
await tester.pumpAndSettle();
expect(find.text('Hələ tapşırıq yoxdur'), findsOneWidget);
});
testWidgets('xəta halında yenidən yoxla düyməsi görünür', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
// Provider-i birbaşa xəta atan implementasiya ilə əvəz edirik.
todosProvider.overrideWith(() => ThrowingTodosNotifier()),
],
child: const MaterialApp(home: TodoPage()),
),
);
await tester.pumpAndSettle();
expect(find.text('Yenidən yoxla'), findsOneWidget);
});
}Widget testi: `ProviderScope(overrides: ...)` ilə fake asılılıq.
| Məqsəd | API |
|---|---|
| Test üçün izolyasiya olunmuş konteyner | `ProviderContainer.test()` — test bitəndə avtomatik sökülür |
| Cari dəyəri oxumaq | `container.read(provider)` |
| Dəyişiklikləri izləmək və autoDispose-un qarşısını almaq | `container.listen(provider, (prev, next) {...})` |
| Async nəticəni gözləmək | `await container.read(provider.future)` |
| Asılılığı əvəz etmək | `overrideWith(...)` / `overrideWithValue(...)` |
| Widget testində əvəzləmə | `ProviderScope(overrides: [...])` |
Müsahibədə vurğulamağa dəyən üstünlük: Provider paketində widget testi üçün provider ağacını əl ilə qurmaq lazımdır, BLoC-da MockBloc yazılır — Riverpod-da isə hər provider heç bir əlavə hazırlıq olmadan override oluna bilir. Bu, xüsusilə repository/service qatını əvəz edərkən test kodunu qısaldır: UI toxunulmur, yalnız asılılıq dəyişir.
📚 Mənbələr və sənədlər
- Provider-lərin test edilməsirəsmiriverpod.dev
ProviderContainer.test(), container.listen, override-lar və konteynerlərin paylaşılmaması xəbərdarlığı.
- Override-larrəsmiriverpod.dev
- ProviderContainer və ProviderScoperəsmiriverpod.dev
- Flutter: widget testlərinə girişrəsmidocs.flutter.dev