【问题标题】:How to implement widget tests by using MockBloc?如何使用 MockBloc 实现小部件测试?
【发布时间】:2021-07-11 12:34:30
【问题描述】:

我正在尝试实现小部件测试以测试登录表单。这个测试取决于我使用 MockBloc 模拟的一个块。但是,它会引发以下错误:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK╞════════════════════════════════════════════════════
The following StateError was thrown running a test:
Bad state: No method stub was called from within `when()`. Was a real method called, or perhaps an 
extension method?

我在下面的link 中发现了一个类似的错误,但我看不出它如何帮助我解决我的问题。

我还查看了以下file on gitlub,这是使用 bloc_test 进行小部件测试的示例。该链接可以在 Bloc 图书馆的官方网站上找到 - 特别是在Todos App in Flutter using the Bloc library

但是,该示例使用的是bloc_test: ^3.0.1,而我使用的是bloc_test: ^8.0.0,可以找到here

这是一个最小的例子:

  • 登录表单小部件
class LoginForm extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Form(
      key: '_loginForm',
      child: Column(
        children: <Widget>[
           ...
           BlocConsumer<AuthenticationBloc, AuthenticationState>(
             listener: (context, state) {
               ...
             },
             builder: (context, state) {
               if (state is AuthenticationInitial) {
                 ...
               } else if (state is LoggingIn || state is LoggedIn) {
                 ...
               } else if (state is Error) { 
                 return Column(
                  children: <Widget>[
                    ...
                    Message(
                      message: state.message,
                      messageContainerWidth: 290,
                      messageContainerHeight: 51,
                    ),
                    ...
                  ],
                );
               }
             }
           ),
        ],
      ),
    );
  }
}
  • 消息小部件
class Message extends StatelessWidget {
  final String message;
  final double messageContainerWidth;
  final double messageContainerHeight;

  ...
  @override
  Widget build(BuildContext context) {
    return Container(
      width: messageContainerWidth,
      height: messageContainerHeight,
      child: Center(
        child: message != ""
            ? Text(
                message,
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: Color.fromRGBO(242, 241, 240, 1),
                  fontSize: 15,
                ),
              )
            : child,
      ),
    );
  }
}
  • 小部件测试(我想测试验证状态为错误时是否显示消息)
...
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
...

// Mocking my LoginUser usecase
class MockLoginUser extends Mock implements LoginUser {}

// Mocking my bloc
class MockAuthenticationBloc
    extends MockBloc<AuthenticationEvent, AuthenticationState>
    implements AuthenticationBloc {}

class AuthenticationStateFake extends Fake implements AuthenticationState {}

void main() {
  MockLoginUser mockLoginUser;

  setUpAll(() {
    registerFallbackValue<AuthenticationState>(AuthenticationStateFake());
  });

  setUp(() {
    mockLoginUser = MockLoginUser();
    authenticationBloc = AuthenticationBloc(loginUser: mockLoginUser);
  });

  group('Login', () {
    testWidgets(
        'should show a Message when the Authentication state is Error',
        (WidgetTester tester) async {
      whenListen(
        authenticationBloc,
        Stream.fromIterable(
          [
            LoggingIn(),
            Error(
              message: 'Some error message',
            ),
          ],
        ),
        initialState: AuthenticationInitial(),
      );
     
      final widget = LoginForm();
      await tester.pumpWidget(
         BlocProvider<AuthenticationBloc>(
          create: (context) => authenticationBloc,
          child: MaterialApp(
            title: 'Widget Test',
            home: Scaffold(body: widget),
          ),
        ),
      );
      await tester.pumpAndSettle();

      final messageWidget = find.byType(Message);
      expect(messageWidget, findsOneWidget);
    });
  });
}

如果有人可以帮助我解决错误,或者可以让我知道实现小部件测试的另一种方法,我将不胜感激。

提前致谢!

【问题讨论】:

    标签: flutter flutter-test widget-test-flutter bloc-test


    【解决方案1】:

    我解决了这个问题,我想分享答案,以防有人发现同样的问题。

    首先,这个link 真的很有帮助。

    解决方案是通过以下方式更改 Widget 测试

    ...
    import 'package:bloc_test/bloc_test.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:flutter_test/flutter_test.dart';
    import 'package:mocktail/mocktail.dart';
    ...
    
    class MockAuthenticationBloc
        extends MockBloc<AuthenticationEvent, AuthenticationState>
        implements AuthenticationBloc {}
    
    class AuthenticationStateFake extends Fake implements AuthenticationState {}
    
    class AuthenticationEventFake extends Fake implements AuthenticationEvent {}
    
    void main() {
      group('Login', () {
    
        setUpAll(() {
          registerFallbackValue<AuthenticationState>(AuthenticationStateFake());
          registerFallbackValue<AuthenticationEvent>(AuthenticationEventFake());
        });
    
        testWidgets(
            'should show a Message when the Authentication state is Error',
            (WidgetTester tester) async {
          // arrange
          final mockAuthenticationBloc = MockAuthenticationBloc();
          when(() => mockAuthenticationBloc.state).thenReturn(
            LoggingIn(), // the desired state
          );
    
          // find
          final widget = LoginForm();
          final messageWidget = find.byType(Message);
    
          // test
          await tester.pumpWidget(
             BlocProvider<AuthenticationBloc>(
              create: (context) => mockAuthenticationBloc,
              child: MaterialApp(
                title: 'Widget Test',
                home: Scaffold(body: widget),
              ),
            ),
          );
          await tester.pumpAndSettle();
    
          // expect
          expect(messageWidget, findsOneWidget);
        });
      });
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-21
      • 2019-12-27
      • 2012-10-24
      • 2021-01-21
      • 2021-05-14
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 2011-01-30
      相关资源
      最近更新 更多