Bloc: Help with test

Created on 12 Dec 2019  路  3Comments  路  Source: felangel/bloc

Describe the bug
Error on mock the bloc to test widgets. The tests were written on a version pre 1.0.0 of the bloc.

To Reproduce
Here an example of code:

class MockHintBloc extends Mock implements HintBloc {}

HintBloc bloc;

void main() {
  BehaviorSubject<HintState> hintStream;

  setUp(() {
    bloc = MockHintBloc();
    hintStream = BehaviorSubject<HintState>();

    when(bloc.state).thenAnswer(
      (_) => hintStream.value,
    );
  });

  tearDown(() {
    hintStream.close();
  });

  testWidgets('Test state HintState.initial', (tester) async {
    hintStream.add(HintState.initial());

    await _createWidget(tester);

    expect(find.byType(SizedBox), findsOneWidget);
  });
}

Future<void> _createWidget(
  WidgetTester tester,
) async {
  await tester.pumpWidget(
    PlatformApp(
      localizationsDelegates: const [
        AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: const [Locale('pt', 'BR')],
      home: BlocProvider<HintBloc>(
        create: (context) => bloc,
        child: const HintWidget(),
      ),
    ),
  );

  await tester.pump();
}

Expected behavior
I try to change the test to:

class MockHintBloc extends MockBloc<HintEvent, HintState> implements HintBloc {}

HintBloc bloc;

void main() {
  setUp(() {
    bloc = MockHintBloc();
  });

  testWidgets('Test state HintState.initial', (tester) async {
    whenListen(bloc, Stream.fromIterable([HintState.initial()]));

    await _createWidget(tester);

    expect(find.byType(SizedBox), findsOneWidget);
  });
}

Future<void> _createWidget(
  WidgetTester tester,
) async {
  await tester.pumpWidget(
    PlatformApp(
      localizationsDelegates: const [
        AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: const [Locale('pt', 'BR')],
      home: BlocProvider<HintBloc>(
        create: (context) => bloc,
        child: const HintWidget(),
      ),
    ),
  );

  await tester.pump();
}

But the state is null on BlocBuilder of my widget.

What is the correct way to mock the bloc to achieve a determinate state on BlocBuilder?

bloc_test question

Most helpful comment

Yes, that helps.
Thanks

All 3 comments

The test ran with the following code:

class MockHintBloc extends MockBloc<HintEvent, HintState> implements HintBloc {}

HintBloc bloc;

void main() {
  BehaviorSubject<HintState> hintStream;

  setUp(() {
    bloc = MockHintBloc();
    hintStream = BehaviorSubject<HintState>();

    when(bloc.state).thenAnswer(
      (_) => hintStream.value,
    );
  });

  tearDown(() {
    hintStream.close();
  });

  testWidgets('Test state HintState.initial', (tester) async {
    final state = HintState.initial();
    hintStream.add(state);

    await _createWidget(tester);

    expect(find.byType(SizedBox), findsOneWidget);
  });
}

Future<void> _createWidget(
  WidgetTester tester,
) async {
  await tester.pumpWidget(
    PlatformApp(
      localizationsDelegates: const [
        AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: const [Locale('pt', 'BR')],
      home: BlocProvider<HintBloc>(
        create: (context) => bloc,
        child: const HintWidget(),
      ),
    ),
  );

  await tester.pump();
}

Is there a better way?

Hi @mateusfsilva 馃憢
Thanks for opening an issue!

I'm glad you managed to get everything working but I think you should be able to simplify your test even further by refactoring your test to

class MockHintBloc extends MockBloc<HintEvent, HintState> implements HintBloc {}

void main() {
  HintBloc bloc;

  setUp(() {
    bloc = MockHintBloc();
  });

  tearDown(() {
    bloc.close();
  });

  testWidgets('Test state HintState.initial', (tester) async {
    when(bloc.state).thenReturn(HintState.initial());
    await _createWidget(tester);
    expect(find.byType(SizedBox), findsOneWidget);
  });
}

Future<void> _createWidget(
  WidgetTester tester,
) async {
  await tester.pumpWidget(
    PlatformApp(
      localizationsDelegates: const [
        AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: const [Locale('pt', 'BR')],
      home: BlocProvider<HintBloc>.value(
        value: bloc,
        child: const HintWidget(),
      ),
    ),
  );

  await tester.pump();
}

Let me know if that helps 馃憤

Yes, that helps.
Thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Reidond picture Reidond  路  3Comments

krusek picture krusek  路  3Comments

komapeb picture komapeb  路  3Comments

wheel1992 picture wheel1992  路  3Comments

abinvp picture abinvp  路  3Comments