dart – 如何在Flutter小部件测试中等待未来完成?
发布时间:2020-12-14 14:51:43 所属栏目:百科 来源:网络整理
导读:我正在尝试执行小部件测试,特别是导航测试.我正在使用bloc体系结构,在bloc上设置流会触发bloc内部的一系列事件,从服务器调用获取会话信息(返回会话信息对象的未来),在成功的服务器调用上设置登录流并且widget具有对此流的流订阅并导航到下一个屏幕. 我正在使
我正在尝试执行小部件测试,特别是导航测试.我正在使用bloc体系结构,在bloc上设置流会触发bloc内部的一系列事件,从服务器调用获取会话信息(返回会话信息对象的未来),在成功的服务器调用上设置登录流并且widget具有对此流的流订阅并导航到下一个屏幕.
我正在使用mockito来模拟服务器调用并对服务器调用进行存根以返回成功响应的未来.问题是当我调用pumpAndSettle()时,它正在超时,因为它没有等待将来完成并返回成功响应. 如果我不是很清楚,我道歉,但这里是示例代码: login_bloc.dart class LoginBloc { LoginRepository _loginRepository; final String searchKeyword = "special-keyword"; final _urlString = PublishSubject<String>(); final _isLoggedIn = BehaviorSubject<bool>(seedValue: false); final _errorMessage = PublishSubject<String>(); Observable<bool> get isLoggedIn => _isLoggedIn.stream; Observable<String> get isErrorState => _errorMessage.stream; LoginBloc({LoginRepository loginRepository}) : _loginRepository = loginRepository ?? LoginRepository() { // Listen on the _urlString stream to call the function which checks for the special keyword and if a match is found make a server call _urlString.stream.listen((String url) { _authorizationFullService(url); }); } // Search for special keyword and if a match is found call the server call function void _authorizationFullService(String url) { if (url.contains(searchKeyword)) { int index = url.indexOf(searchKeyword); String result = url.substring(index + searchKeyword.length); result = result.trim(); String decodedUrl = Uri.decodeFull(result); if (decodedUrl != null && decodedUrl.length > 0) { _fullServiceServerCall(decodedUrl); } else { _isLoggedIn.sink.add(false); } } } // Call server call function from repository which returns a future of the Authorization object void _fullServiceServerCall(String decodedUrl) { _loginRepository .getSession(decodedUrl) .then(_handleSuccessAuthorization) .catchError(_handleErrorState); } // Handle success response and set the login stream void _handleSuccessAuthorization(Authorization authorization) { if (authorization != null && authorization.idnumber != 0) { _isLoggedIn.sink.add(true); } else { _isLoggedIn.sink.add(false); } } // Handle error response and set the error stream void _handleErrorState(dynamic error) { _isLoggedIn.sink.add(false); _errorMessage.sink.add(error.toString()); } void dispose() { _urlString.close(); _isLoggedIn.close(); _errorMessage.close(); } } widget_test.dart group('Full Login Navigation test',() { LoginRepository mockLoginRepository; LoginBloc loginBloc; NotificationBloc notificationBloc; NavigatorObserver mockNavigatorObserver; Authorization _auth; String testUrl; setUp(() { mockLoginRepository = MockLoginRepository(); _auth = Authorization((auth) => auth ..param1 = "foo" ..param2 = "bar" ..param3 = "foobar" ..param4 = "barfoo"); loginBloc = LoginBloc(loginRepository: mockLoginRepository); mockNavigatorObserver = MockNavigatorObserver(); testUrl = "http://test.test.com"; }); Future<Null> _buildFullLoginPage(LoginBloc loginBloc,NotificationBloc notificationBloc,WidgetTester tester) async { when(mockLoginRepository.getSession(testUrl)) .thenAnswer((_) => Future.value(_auth)); await tester.pumpWidget(LoginBlocProvider( child: NotificationBlocProvider( child: MaterialApp( home: LoginFullService(),onGenerateRoute: NavigationRoutes.routes,navigatorObservers: [mockNavigatorObserver],),notificationBloc: notificationBloc,loginBloc: loginBloc,)); //TODO: Remove casting to dynamic after dart sdk bug fix: https://github.com/dart-lang/mockito/issues/163 verify(mockNavigatorObserver.didPush(any,any) as dynamic); loginBloc.getAuthorization( "http://testing.testing.com?search-keyword=http%3A%2F%2Ftest.test.com"); } testWidgets('Navigate to landing page on correct login url',(WidgetTester tester) async { await _buildFullLoginPage(loginBloc,notificationBloc,tester); await tester.pumpAndSettle(); expect(find.byKey(Key('webview_scaffold')),findsNothing); //TODO: Remove casting to dynamic after dart sdk bug fix: https://github.com/dart-lang/mockito/issues/163 verify(mockNavigatorObserver.didPush(any,any) as dynamic); }); }); 在运行小部件测试时,testWidgets中的tester.pumpAndSettle()在未来完成之前超时.这是错误日志: ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════ The following assertion was thrown running a test: pumpAndSettle timed out When the exception was thrown,this was the stack: #0 WidgetTester.pumpAndSettle.<anonymous closure> (package:flutter_test/src/widget_tester.dart:299:11) <asynchronous suspension> #3 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:69:41) #4 WidgetTester.pumpAndSettle (package:flutter_test/src/widget_tester.dart:295:27) #5 main.<anonymous closure>.<anonymous closure> (file:///Users/ssiddh/Documents/projects/mobile-flutter/test/ui/pages/login/login_full_test.dart:114:20) <asynchronous suspension> #6 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:72:23) #7 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:555:19) <asynchronous suspension> #10 TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:539:14) #11 AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:883:24) #17 AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:880:15) #18 testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:71:22) #19 Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test/src/backend/declarer.dart:168:27) <asynchronous suspension> #20 Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test/src/backend/invoker.dart:249:15) <asynchronous suspension> #25 Invoker.waitForOutstandingCallbacks (package:test/src/backend/invoker.dart:246:5) #26 Declarer.test.<anonymous closure>.<anonymous closure> (package:test/src/backend/declarer.dart:166:33) #31 Declarer.test.<anonymous closure> (package:test/src/backend/declarer.dart:165:13) <asynchronous suspension> #32 Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test/src/backend/invoker.dart:403:25) <asynchronous suspension> #46 _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19) #47 _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5) #48 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:169:12) (elided 30 frames from class _FakeAsync,package dart:async,and package stack_trace) 我真的很感激任何帮助或反馈. 解决方法
尝试用你的测试包装
testWidgets('Navigate to landing page on correct login url',(WidgetTester tester) async { await tester.runAsync(() async { // test code here }); }); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |