Bloc: [Question] How to use mockito verify while testing blocs?

Created on 22 Mar 2019  路  3Comments  路  Source: felangel/bloc

Hello

I would like to understand a little bit how can i use verify while testing a bloc. I wasn't able to find any example around and all my attempt have failed, leaving me no other options that put my verify checks into the tearDown statement which of course is not optimal.

The issue I encounter is basically that when the test runs, the verify method have been called before mapEventToState resulting in make my test fail.

Code example

auth_bloc.dart

import 'package:bloc/bloc.dart';
import 'package:checkin/src/blocs/auth/auth_event.dart';
import 'package:checkin/src/blocs/auth/auth_state.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:meta/meta.dart';

class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final FirebaseAuth auth;

  AuthBloc({
    @required this.auth
  });

  @override
  AuthState get initialState => AuthUninitialized();

  @override
  Stream<AuthState> mapEventToState(AuthState currentState, AuthEvent event) async* {
    /*
     ...
    */
    if (event is LoggedOut) {
      this.auth.signOut();
      yield AuthUnauthenticated();
    }
  }
}

auth_bloc_test.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:mockito/mockito.dart';
import 'package:checkin/src/blocs/auth/bloc.dart';
import 'package:test/test.dart';

class MockFirebaseAuth extends Mock implements FirebaseAuth {}
class MockFirebaseUser extends Mock implements FirebaseUser {}

void main() {
  group('AuthBloc', () {
    AuthBloc authBloc;
    MockFirebaseAuth firebaseAuth;

    setUp(() {
      firebaseAuth = MockFirebaseAuth();
      authBloc = AuthBloc(auth: firebaseAuth);
    });

    group('dispatch LoggedOut', () {
      setUp(() {
        authBloc.dispatch(LoggedOut());
      });

      //@TODO: not a good solution
      tearDown(() {
        verify(firebaseAuth.signOut()).called(1);
      });
      test("the final state should be AuthAuthenticated and pass the current user", () {
        final expectedState = [
          AuthUninitialized(),
          AuthUnauthenticated(),
        ];

        expectLater(
          authBloc.state,
          emitsInOrder(expectedState),
        );
      });
    });
 });
}
question

Most helpful comment

Amazing! Thank you so much for the fast reply and for this library, it makes coding with Blocs SO smooth!

All 3 comments

Hey @nerder 馃憢

Great question! You can do the verification in the then of the expectLater like:

expectLater(authBloc.state, emitsInOrder(expectedState)).then(() {
  verify...
});

You can check out a todos app that is fully tested at the flutter_architecture_samples for more details.

Hope that helps! 馃憤

Amazing! Thank you so much for the fast reply and for this library, it makes coding with Blocs SO smooth!

Hey @nerder 馃憢

Great question! You can do the verification in the then of the expectLater like:

expectLater(authBloc.state, emitsInOrder(expectedState)).then(() {
  verify...
});

You can check out a todos app that is fully tested at the flutter_architecture_samples for more details.

Hope that helps! 馃憤

then() waits for a FutureOr<T> so you need to set the returning type <T>, in this case, <void>. And you need to declare the callback param, so you need to add, at least _ :

expectLater(authBloc.state, emitsInOrder(expectedState)).then<void>((_) =>  verify(repository.foo()).called(1));

Can be pretty obvious but I spent some time to figure it out, helping others to do not.

Was this page helpful?
0 / 5 - 0 ratings