#flutter #riverpod #widget-test-flutter
Вопрос:
ОБНОВЛЕНИЕ: Переписал тест так же, как я тестирую другой потребительский виджет, который действительно работает, но он все еще не работает для моего теста, и я не могу понять, почему 🙁 Текущий подход:
void main() {
final List<Exercise> _mockExercises = [
Exercise(
userID: 'uid123',
title: 'Übung1',
repetitions: 10,
isCompleted: false,
isVideo: false,
unit: 'Sekunden',
description: 'Some description',
exerciseID: '42',
imageUrl: 'https://via.placeholder.com/150',
thumbUrl: 'https://via.placeholder.com/150'),
Exercise(
userID: 'uid123',
title: 'Übung2',
repetitions: 20,
isCompleted: false,
isVideo: false,
unit: 'Sekunden',
description: 'Some description2',
exerciseID: '43',
imageUrl: 'https://via.placeholder.com/150',
thumbUrl: 'https://via.placeholder.com/150'),
];
testWidgets('user exercise list - pump', (WidgetTester tester) async {
await mockNetworkImagesFor(() async {
await tester.pumpWidget(ProviderScope(
child: MyApp(),
/// overrides: provide fake asyncvalue data to stream
overrides: [
exerciseCollectionStream
.overrideWithValue(AsyncValue.data(_mockExercises))
],
));
await tester.pump();
// The first frame is a loading state.
expect(find.byType(Loading), findsOneWidget);
await tester.pumpAndSettle();
// await Future.delayed(Duration(seconds: 2));
// await tester.pumpAndSettle();
// No-longer loading
expect(find.byType(Loading), findsNothing);
});
});
}
Я пытаюсь написать тест виджета для виджета Listview, и я никогда не перехожу в состояние загрузки «Asyncvalue».когда состояние в моем тесте и оно застряло в загрузке.
Я попытался подойти к тесту, как в документах Riverpod, или как описано здесь: https://codewithandrea.com/videos/flutter-state-management-riverpod/
Но я застрял :-/ У нас есть виджет загрузки (), который мы тестируем, чтобы увидеть, исчезнет ли он, но это не так..
Это код теста:
class ExerciseRepo {
// ignore: missing_return
Future<List<Exercise>> exerciseList() {
// should get data from database
}
}
final exerciseRepoProvider = Provider((ref) => ExerciseRepo());
final exerciseListProvider = FutureProvider<List<Exercise>>((ref) {
final repo = ref.watch(exerciseRepoProvider);
return repo.exerciseList();
});
class MockExercisesRepository extends Mock implements ExerciseRepo {
@override
Future<List<Exercise>> exerciseList() {
return Future.value([
Exercise(
title: 'Übung1',
repetitions: 10,
isCompleted: false,
isVideo: false,
unit: 'Sekunden',
description: 'Some description',
exerciseID: '42',
imageUrl: 'https://via.placeholder.com/150',
thumbUrl: 'https://via.placeholder.com/150'),
Exercise(
title: 'Übung2',
repetitions: 20,
isCompleted: false,
isVideo: false,
unit: 'Sekunden',
description: 'Some description2',
exerciseID: '43',
imageUrl: 'https://via.placeholder.com/150',
thumbUrl: 'https://via.placeholder.com/150'),
]);
}
}
void main() {
testWidgets('override repositoryProvider', (WidgetTester tester) async {
await mockNetworkImagesFor(() async {
await tester.pumpWidget(
ProviderScope(
overrides: [
exerciseListProvider.overrideWithProvider(
Provider((ref) => MockExercisesRepository))
],
child: MaterialApp(
home: Builder(builder: (context) {
return UserExerciseList();
}),
),
),
);
// The first frame is a loading state.
expect(find.byType(Loading), findsOneWidget);
await tester.pump();
await tester.pumpAndSettle();
// await Future.delayed(Duration(seconds: 3));
await tester.pumpAndSettle();
// No-longer loading
expect(find.byType(Loading), findsNothing);
});
});
}
The error message is:
The following TestFailure object was thrown running a test:
Expected: no matching nodes in the widget tree
Actual: _WidgetTypeFinder:<exactly one widget with type "Loading" (ignoring offstage widgets):
Loading>
Which: means one was found but none were expected
When the exception was thrown, this was the stack:
#4 main.<anonymous closure>.<anonymous closure> (file:///.../test/widget_exercise_list_test.dart:77:7)
<asynchronous suspension>
#5 main.<anonymous closure>.<anonymous closure> (file:///.../test/widget_exercise_list_test.dart)
#10 HttpOverrides.runZoned (dart:_http/overrides.dart:55:26)
#11 mockNetworkImagesFor (package:network_image_mock/src/network_image_mock.dart:9:24)
#12 main.<anonymous closure> (file:///.../test/widget_exercise_list_test.dart:54:11)
#13 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:146:29)
<asynchronous suspension>
#14 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#15 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:784:19)
<asynchronous suspension>
#18 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:764:14)
#19 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1173:24)
#20 FakeAsync.run.<anonymous closure>.<anonymous closure> (package:fake_async/fake_async.dart:178:54)
#25 withClock (package:clock/src/default.dart:48:10)
#26 FakeAsync.run.<anonymous closure> (package:fake_async/fake_async.dart:178:22)
#31 FakeAsync.run (package:fake_async/fake_async.dart:178:7)
#32 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1170:15)
#33 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:138:24)
#34 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:175:19)
<asynchronous suspension>
#35 Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)
#40 Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:173:13)
#41 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:231:15)
#46 Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:228:5)
#47 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:383:17)
<asynchronous suspension>
#48 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart)
#53 Invoker._onRun.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:370:9)
#54 Invoker._guardIfGuarded (package:test_api/src/backend/invoker.dart:415:15)
#55 Invoker._onRun.<anonymous closure> (package:test_api/src/backend/invoker.dart:369:7)
#62 Invoker._onRun (package:test_api/src/backend/invoker.dart:368:11)
#63 LiveTestController.run (package:test_api/src/backend/live_test_controller.dart:153:11)
#64 RemoteListener._runLiveTest.<anonymous closure> (package:test_api/src/remote_listener.dart:256:16)
#69 RemoteListener._runLiveTest (package:test_api/src/remote_listener.dart:255:5)
#70 RemoteListener._serializeTest.<anonymous closure> (package:test_api/src/remote_listener.dart:208:7)
#88 _GuaranteeSink.add (package:stream_channel/src/guarantee_channel.dart:125:12)
#89 new _MultiChannel.<anonymous closure> (package:stream_channel/src/multi_channel.dart:159:31)
#93 CastStreamSubscription._onData (dart:_internal/async_cast.dart:85:11)
#127 new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1145:21)
#135 _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:338:23)
#136 _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:232:46)
#146 _Socket._onData (dart:io-patch/socket_patch.dart:2044:41)
#155 new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1580:33)
#156 _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1076:14)
(elided 115 frames from dart:async and package:stack_trace)
This was caught by the test expectation on the following line:
file:///.../test/widget_exercise_list_test.dart line 77
The test description was:
override repositoryProvider
════════════════════════════════════════════════════════════════════════════════════════════════════
Test failed. See exception logs above.
The test description was: override repositoryProvider
Это соответствующая часть UserExerciseList()
@override
Widget build(BuildContext context, ScopedReader watch) {
AsyncValue<List<Exercise>> userExercisesList =
watch(exerciseCollectionStream);
return userExercisesList.when(
error: (error, stack) => ErrorInfo(error, stack),
loading: () => Loading(),
data: (List<Exercise> exercises) {
Я также заменил Future на stream в своих тестах, тоже не сработало :-/ Любая помощь высоко ценится!
Большое спасибо!
Комментарии:
1. Любая возможная помощь..? Вероятно, публикация в день flutter engage была не слишком многообещающей, так как в настоящее время всем очень любопытно 🙂
2. вы пробовали добавить ожидание будущего? задерживается в вашем издевательском списке упражнений ?
3. Спасибо за идею, к сожалению, она не работает 🙁
4. Я также переписал весь тест на более простую версию, которая на самом деле отлично работает аналогично другому тесту виджета, но этот конкретный тест все равно не проходит, и тест все равно проваливается.
5. У кого-нибудь еще есть идея? Все еще борется 🙁
Ответ №1:
Мне пришлось попробовать использовать несколько pump
s, чтобы получить мои фиктивные данные для возврата и изменения состояния.
await tester.pumpWidget(ProviderScope(child: const MyApp()));
await tester.pump(Duration(seconds: 1));
await tester.pump(Duration(seconds: 1));
await tester.pump(Duration(seconds: 1));
expect(find.text("Sample Text"), findsOneWidget);
pumpAndSettle
не получилось.