如何在Flutter小部件测试中等待将来完成?

时间:2018-09-05 03:50:04

标签: dart flutter flutter-test

我正在尝试执行小部件测试,特别是导航测试。我正在使用bloc架构,在bloc上设置流将触发bloc内的一系列事件,从服务器调用获取会话信息(返回会话信息对象的未来),在成功的服务器调用上设置登录流,并且小部件具有对此流的流订阅,并导航到下一个屏幕。

我正在使用Mockito模拟服务器调用,并对服务器调用进行存根以返回成功响应的未来。问题是当我打电话给<script src="https://code.jquery.com/jquery-3.3.1.js"></script> <div class="progressbar-wrapper"> <div class="progressbar"> <div class="side front"> <div class="bar"></div> </div> </div> </div>时,它已经超时了,因为它不等待将来完成并返回成功响应。

如果我不太清楚的话,我表示歉意,但这是示例代码:

login_bloc.dart

pumpAndSettle()

widget_test.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();
  }
}

在运行窗口小部件时,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); }); }); 内的tester.pumpAndSettle()会在将来完成之前超时。这是错误日志:

testWidgets

我将非常感谢您提供的任何帮助或反馈。

1 个答案:

答案 0 :(得分:6)

尝试用

testWidgets('Navigate to landing page on correct login url',
    (WidgetTester tester) async {
    await tester.runAsync(() async {

      // test code here

    });
 });