使用BLoC模式测试小部件

时间:2018-11-26 22:12:47

标签: unit-testing flutter rxdart

我一直在学习Flutter / Dart和BLoC模式。我以本文为起点: https://www.didierboelens.com/2018/08/reactive-programming---streams---bloc/

我可以使用bloc类和窗口小部件,但是我不知道如何测试窗口小部件。如本文所述,我正在使用BlocProvider,但是我不知道如何为小部件提供模拟的bloc类。

如果我有这样的代码:

@override
Widget build(BuildContext context) {
  final ProfileBloc profileBloc = BlocProvider.of<ProfileBloc>(context);

  return Scaffold(
      body: Container(
        child: StreamBuilder<AuthModel>(
          stream: profileBloc.outAuthModel,
          initialData: null,
          builder: (BuildContext context, AsyncSnapshot<AuthModel> snapshot) {
            if (snapshot.hasData) {
              return buildProfilePage(context, snapshot.data.profile);
            }
            return buildStartPage();
          },
        ),
      ));
}

我想模拟我的ProfileBloc,但是它是在我的build()函数中创建的,并且需要上下文。如何测试此小部件?我想我需要一种传递模拟的ProfileBloc的方法,但是我不知道该怎么做。我要确保小部件的行为符合预期。

2 个答案:

答案 0 :(得分:0)

在此示例中,您使用BlocProvider来获取ProfileBloc,但是您可以使用final ProfileBloc profileBloc = ProfileBloc;直接创建新的集团。使用外部块并不重要,因为这是在小部件测试之后进行的。

答案 1 :(得分:0)

测试小部件时,我遇到了完全相同的问题,并且能够解决它。这是无法使用的“ Before Code”,而起到了窍门的“ After Code” ...

代码之前

请注意,在抽取窗口小部件时,MaterialApp被设置为最顶部的窗口小部件。

Future<Null> _buildRideCard(WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp( // top most widget 
        localizationsDelegates: [
          AppLocalizationsDelegate(),
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate
        ],
        //some other stuff, irrelevant for this example
        
      ));
    }

之后的代码

请注意,MaterialApp小部件现在如何用BlocProvider包装,并且它的blocProviders属性提供了小部件测试所需的Bloc列表。这解决了我的问题,现在我的窗口小部件测试中没有任何关于上下文的问题。希望能有所帮助;)

Future<Null> _buildRideCard(WidgetTester tester) async {
      await tester.pumpWidget(BlocProviderTree( // <- magic #1
        blocProviders: [ <- magic #2
          BlocProvider<RideDetailsBloc>(
              bloc: RideDetailsBloc(_setupRidesRepo()))
        ],
        child: MaterialApp(
          localizationsDelegates: [
            AppLocalizationsDelegate(),
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate
          ],
          //some other stuff, irrelevant for this example
        ),
      ));
    }