BlocBuilder 小部件的 Flutter 小部件测试

Posted

技术标签:

【中文标题】BlocBuilder 小部件的 Flutter 小部件测试【英文标题】:Flutter Widget Testing for BlocBuilder Widgets 【发布时间】:2021-05-09 16:15:26 【问题描述】:

我有一个小部件,它使用 bloc 构建器来映射小部件的不同状态。

class BodyWidget extends StatelessWidget 
      @override
      Widget build(BuildContext context) 
        return BlocBuilder<NewsBloc, NewsState>(builder: (context, state) 
          return state.map(
            .....
          );
        );
      
    ....
    

BodyWidget 是在一个带有 BlocProvider 的 Widget 中创建的。

class MainPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return BlocProvider(
      create: (context) =>
          getIt<NewsBloc>()..add(const NewsEvent.fetchNewsData()),
      child: BodyWidget(),
    );
  
....

NewsBloc 被定义为

@injectable
class NewsBloc extends Bloc<NewsEvent, NewsState> 
  final GetNews getNews;
  NewsBloc(
    @required this.getNews,
  ) : super(const _Initial());

  @override
  Stream<NewsState> mapEventToState(
    NewsEvent event,
  ) async*  ... 

我正在使用get_it 和injectable 进行依赖注入。

现在我正在尝试为BodyWidget 编写一个简单的小部件测试,但我不太确定如何在测试中注入所有这些依赖项。

class MockBuildContext extends Mock implements BuildContext 

class MockNewsBloc extends Mock implements NewsBloc 

void main() 
  ForYouNewsTab _widget;
  MockBuildContext _context;
  NewsBloc _newsBloc;

  Widget makeTestableWidgets(Widget child) 
    return MaterialApp(
      home: Scaffold(
        // body: BlocProvider(
        //   create: (_context) => getIt<NewsBloc>(),
        //   child: child,
        // ),
        body: child,
      ),
    );
  

  setUp(() 
    _context = MockBuildContext();
    _widget = ForYouNewsTab();
  );

  test('ForYouNewsTab is sub class of StatelessWidget', () 
    expect(_widget, isA<StatelessWidget>());
  );

  testWidgets('should return sized box for initial state',
      (WidgetTester tester) async 
    await tester.pumpWidget(makeTestableWidgets(child: _widget));
  );

我在 *** 中进行了搜索,但找不到适合我的解决方案。

【问题讨论】:

【参考方案1】:

我按照非常基本的步骤解决了我的问题。不太确定它是否正确。无论如何,如果有人遇到同样的问题,它可能会对他们有所帮助。

class MainPage extends StatelessWidget 

  //added line
  final NewsBloc newsBloc;

  const MainPage(
    Key key, 
    @required this. newsBloc,
  )

  @override
  Widget build(BuildContext context) 
    return BlocProvider(
      // changed line
      // create: (context) => getIt<NewsBloc>()..add(const NewsEvent.fetchNewsData()),
      create: (context) => newsBloc..add(const NewsEvent.fetchNewsData()),
      child: BodyWidget(),
    );
  

  ....

 

现在在我的测试用例中,我可以创建 MockNewsBloc 并在测试时将其轻松注入 MainPage。

【讨论】:

以上是关于BlocBuilder 小部件的 Flutter 小部件测试的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:两个连续页面上的相同 BlocBuilder

在 Flutter 中使用 BLoC - 在有状态小部件与无状态小部件中的使用

动画切换器和 Bloc Builder

嵌套 BlocBuilders 以管理同一个小部件上的多个状态

在重建时 Flutter 重用 StatefulWidget 的状态

一起使用flutter bloc库和websockets的设计建议