BlocBuilder 小部件的 Flutter 小部件测试

时间:2021-02-05 10:07:44

标签: flutter testing dependency-injection bloc widget-test-flutter

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

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

BodyWidget 是在带有 BlocProvider 的小部件中创建的。

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_itinjectable 进行依赖注入。

现在我正在尝试为 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));
  });
}

我确实在 stackoverflow 中搜索过,但找不到适合我的解决方案。

1 个答案:

答案 0 :(得分:0)

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

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。