【问题标题】:Flutter-Test: Getting BlocProvider.of() called with a context that does not container BlocFlutter-Test:使用不包含 Bloc 的上下文调用 BlocProvider.of()
【发布时间】:2021-05-02 22:13:38
【问题描述】:

我正在尝试测试我的提交按钮,该按钮会触发 onPress 的 bloc 事件。

SubmitButton.dart - 小部件

class AuthenticationSubmitButton extends StatefulWidget {
  final String buttonLabel;
  final TextEditingController _userEmailController;
  final TextEditingController _passwordController;

  AuthenticationSubmitButton(
      this.buttonLabel, this._userEmailController, this._passwordController);

  @override
  _AuthenticationSubmitButtonState createState() =>
      _AuthenticationSubmitButtonState();
}

class _AuthenticationSubmitButtonState
    extends State<AuthenticationSubmitButton> {
  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;
    final _authBloc = BlocProvider.of<AuthenticationBloc>(context);
    return Container(
      child: FlatButton.icon(
        height: screenSize.height * 0.07,
        minWidth: screenSize.width * 0.5,
        padding: EdgeInsets.all(10),
        color: Colors.green,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
        onPressed: () {
          final email = widget._userEmailController.text.trim();
          final password = widget._passwordController.text.trim();
          _authBloc.add(UserLoginEvent(email, password));
        },
        icon: Icon(Icons.keyboard_return_rounded),
        label: Text(
          widget.buttonLabel,
          style: SubmitButtonStyle,
        ),
      ),
    );
  }
}

如您所见,我正在调用事件 UserLoginEvent

authentication_events.dart

@immutable
abstract class AuthenticationEvent {}

/**
 * Login Event
 * Logout Event
 */

class UserLoginEvent extends AuthenticationEvent {
  final String userEmail;
  final String userPassword;
  UserLoginEvent(this.userEmail, this.userPassword);
}

class ClearLoginEvent extends AuthenticationEvent {
  
}

这是我的身份验证状态

authentication_states.dart

@immutable
abstract class AuthenticationState extends Equatable {

}

class AuthenticationInitial extends AuthenticationState {
  @override
  List<Object> get props => [];
}

/**
 * LoginSuccessful
 * LoginFailed
 * LogoutSuccessful
 */

class LoginSuccessful extends AuthenticationState {
  @override
  List<Object> get props => [];
}

class LoginError extends AuthenticationState {
  @override
  List<Object> get props => [];
}

authentication_bloc.dart

    class AuthenticationBloc
        extends Bloc<AuthenticationEvent, AuthenticationState> {
      AuthenticationBloc({this.userRepository}) : super(AuthenticationInitial());
      UserRepository userRepository;
      @override
      Stream<AuthenticationState> mapEventToState(
        AuthenticationEvent event,
      ) async* {
        if (event is UserLoginEvent) {
          UserRepository repository = userRepository ?? UserRepository();
          try {
            bool loggedIn = await repository.authenticateUserWithCredentials(
                event.userEmail, event.userPassword);
            if (loggedIn) {
              yield LoginSuccessful();
            } else {
              yield LoginError();
            }
          } catch (e) {
            yield EmptyLoginCredentials();
          }
        } else if (event is ClearLoginEvent) {
          yield AuthenticationInitial();
        }
      }
    }

And finally my test for submit button

> submit_button_test.dart

class MockAuthBloc extends MockBloc<AuthenticationState>
    implements AuthenticationBloc {}

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  MockAuthBloc authBloc = MockAuthBloc();
  TextEditingController _userEmailController;
  TextEditingController _passwordController;

  setUp(() {
    _userEmailController = TextEditingController();
    _passwordController = TextEditingController();
    authBloc = MockAuthBloc();
  });

  tearDown(() {
    _userEmailController.dispose();
    _passwordController.dispose();
    authBloc?.close();
  });

  ///Provide Material App for giving access to MediaQuery
  ///Wrap any widget that needs Material widget
  Widget buildTestableWidget(Widget widget) {
    return MediaQuery(
      data: MediaQueryData(),
      child: BlocProvider.value(
        value: authBloc,
        child: MaterialApp(
          home: Material(
            child: widget,
          ),
        ),
      ),
    );
  }

  group('Testing Submit button |', () {
    testWidgets('description', (WidgetTester tester) async {
      whenListen(
        authBloc,
        Stream.fromIterable(<AuthenticationState>[LoginSuccessful()]),
      );

      await tester.pumpWidget(buildTestableWidget(AuthenticationSubmitButton(
          'Submit', _userEmailController, _passwordController)));
      final buttonFinder = find.byType(FlatButton);
      final button = tester.firstWidget(buttonFinder);
    });
  });
}

你能告诉我我在这里做错了什么吗? 以下是我的错误

00:03 +19: /home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart: Testing Submit button | description                                                                
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building AuthenticationSubmitButton(dirty, dependencies:
[MediaQuery], state: _AuthenticationSubmitButtonState#da4f9):
        BlocProvider.of() called with a context that does not contain a Bloc/Cubit of type
AuthenticationBloc.
        No ancestor could be found starting from the context that was passed to
BlocProvider.of<AuthenticationBloc>().

        This can happen if the context you used comes from a widget above the BlocProvider.

        The context used was: AuthenticationSubmitButton(dirty, dependencies: [MediaQuery], state:
_AuthenticationSubmitButtonState#da4f9)


The relevant error-causing widget was:
  AuthenticationSubmitButton
  file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:57:51

When the exception was thrown, this was the stack:
#0      BlocProvider.of (package:flutter_bloc/src/bloc_provider.dart:121:7)
#1      _AuthenticationSubmitButtonState.build (package:kaadhal_host_client/screens/Authentication/widgets/submit_button.dart:26:36)
#2      StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28)
#3      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15)
#4      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
#5      Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
#6      ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4606:5)
#7      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4791:11)
#8      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4601:5)
...     Normal element mounting (174 frames)
#182    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
#183    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6236:32)
...     Normal element mounting (267 frames)
#450    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
#451    Element.updateChild (package:flutter/src/widgets/framework.dart:3327:18)
#452    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4652:16)
#453    _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:426:11)
#454    Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
#455    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4606:5)
#456    ComponentElement.mount (package:flutter/src/widgets/framework.dart:4601:5)
...     Normal element mounting (7 frames)
#463    SingleChildWidgetElementMixin.mount (package:nested/nested.dart:223:11)
...     Normal element mounting (7 frames)
#470    SingleChildWidgetElementMixin.mount (package:nested/nested.dart:223:11)
...     Normal element mounting (7 frames)
#477    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3569:14)
#478    Element.updateChild (package:flutter/src/widgets/framework.dart:3324:20)
#479    RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1252:16)
#480    RenderObjectToWidgetElement.update (package:flutter/src/widgets/binding.dart:1230:5)
#481    RenderObjectToWidgetElement.performRebuild (package:flutter/src/widgets/binding.dart:1244:7)
#482    Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
#483    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2730:33)
#484    AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1088:18)
#485    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:302:5)
#486    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
#487    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1055:9)
#488    AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:961:9)
#491    TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
#492    AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:948:27)
#493    WidgetTester.pumpWidget.<anonymous closure> (package:flutter_test/src/widget_tester.dart:524:22)
#496    TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
#497    WidgetTester.pumpWidget (package:flutter_test/src/widget_tester.dart:521:27)
#498    main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:57:20)
#499    main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:46:32)
#500    testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:146:29)
#511    FakeAsync.flushMicrotasks (package:fake_async/fake_async.dart:193:32)
#512    AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1189:17)
#513    AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1177:35)
(elided 29 frames from dart:async and package:stack_trace)

════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following StateError was thrown running a test:
Bad state: No element

When the exception was thrown, this was the stack:
#0      Iterable.first (dart:core/iterable.dart:524:7)
#1      WidgetController.firstWidget (package:flutter_test/src/controller.dart:79:30)
#2      main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart:60:29)
<asynchronous suspension>
#3      main.<anonymous closure>.<anonymous closure> (file:///home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart)
#4      testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:146:29)
<asynchronous suspension>
#5      testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart)
#6      TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:784:19)
<asynchronous suspension>
#9      TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:764:14)
#10     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1173:24)
#11     FakeAsync.run.<anonymous closure>.<anonymous closure> (package:fake_async/fake_async.dart:178:54)
#16     withClock (package:clock/src/default.dart:48:10)
#17     FakeAsync.run.<anonymous closure> (package:fake_async/fake_async.dart:178:22)
#22     FakeAsync.run (package:fake_async/fake_async.dart:178:7)
#23     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1170:15)
#24     testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:138:24)
#25     Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:175:19)
<asynchronous suspension>
#26     Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart)
#31     Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:173:13)
#32     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:231:15)
#37     Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:228:5)
#38     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:383:17)
<asynchronous suspension>
#39     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart)
#44     Invoker._onRun.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:370:9)
#45     Invoker._guardIfGuarded (package:test_api/src/backend/invoker.dart:415:15)
#46     Invoker._onRun.<anonymous closure> (package:test_api/src/backend/invoker.dart:369:7)
#53     Invoker._onRun (package:test_api/src/backend/invoker.dart:368:11)
#54     LiveTestController.run (package:test_api/src/backend/live_test_controller.dart:153:11)
#55     RemoteListener._runLiveTest.<anonymous closure> (package:test_api/src/remote_listener.dart:256:16)
#60     RemoteListener._runLiveTest (package:test_api/src/remote_listener.dart:255:5)
#61     RemoteListener._serializeTest.<anonymous closure> (package:test_api/src/remote_listener.dart:208:7)
#79     _GuaranteeSink.add (package:stream_channel/src/guarantee_channel.dart:125:12)
#80     new _MultiChannel.<anonymous closure> (package:stream_channel/src/multi_channel.dart:159:31)
#84     CastStreamSubscription._onData (dart:_internal/async_cast.dart:85:11)
#118    new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1145:21)
#126    _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:338:23)
#127    _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:232:46)
#137    _Socket._onData (dart:io-patch/socket_patch.dart:2044:41)
#146    new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1580:33)
#147    _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1076:14)
(elided 111 frames from dart:async and package:stack_trace)

The test description was:
  description
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following message was thrown:
Multiple exceptions (2) were detected during the running of the current test, and at least one was
unexpected.
════════════════════════════════════════════════════════════════════════════════════════════════════
00:03 +19 -1: /home/bhuvanesh/code/kaadhal_host_client/test/screens/Authentication/widgets/submit_button_test.dart: Testing Submit button | description [E]                                                         
  Test failed. See exception logs above.
  The test description was: description

【问题讨论】:

    标签: flutter dart bloc flutter-test


    【解决方案1】:

    原因-

    1. 您即将参加本课程的思想导航器
    2. 你的父母没有使用相同的 bloc

    解决方案-

    你可以在这里使用 bloc 通过将它传递给构造函数

    【讨论】:

      猜你喜欢
      • 2021-02-08
      • 2020-12-26
      • 2020-10-16
      • 2020-08-21
      • 2020-05-11
      • 2020-10-25
      • 2021-05-23
      • 2020-05-20
      • 2020-11-15
      相关资源
      最近更新 更多