简体   繁体   中英

Flutter Mockito Test StreamSubscription onError

I am trying to test a cubit which subscribes to a firebaseAuth listener that is prone to fail and presumably call "onError" on the subscriber.

I am struggling to mock the exception as a subscription does not really "throw" per se, but rather calls onError using a callback.

My cubit defines:

configureUserListener(String uid) {
    userSubscription = _listenToUser(uid).listen((user) async {
      //Do something with the user
    });

    userSubscription!.onError((e) async {
      await logout();
      emit(
        RootCubitError(state.user, e.toString()),
      );
    }
}

My test is structured so when _listenToUser is called, it throws. However, that is not what actually happens when the stream fails. Again, it instead calls onError.

My test:

test('should logout when user listener throws error', () async {
  _auth = MockFirebaseAuth(
    signedIn: true,
    mockUser: MockUser(uid: parent1.id, email: parent1.email),
  );

  var cubit = _cubit(_auth);

  when(_getLoggedInChildId()).thenReturn(null);

  when(_listenToUser(any)).thenThrow(Exception()); //This is wrong, as it throws an error, instead of calling onError

  cubit.init();

  await expectLater(
    cubit.stream,
    emitsInOrder(
      [
        isA<RootCubitError>(),
      ],
    ),
  );

  verify(_sharedPreferences.clear());
  verify(_auth.signOut());
});

and my stream:

  @override
  Stream<User> user(String uid) {
    return FirebaseFirestore.instance
        .collection(FirestoreCollections.users)
        .doc(uid)
        .snapshots()
        .map((doc) => UserModel.fromMap(doc.id, doc.data())); //This map can fail and call onError
  }

Any idea on how I can mock the call to onError in this case?

It is only possible to mock methods of mock classes. For example, in your case you could mock when(_auth.anyMethod(any)).thenThrow(Exception()) because _auth is a mock class.

It's not clear if cubit is a mock class. If it is you could change the method _listenToUser from private to public in your Cubit and add the @visibleForTestign annotation to warn you not to use it unless in a test like so:

@visibleForTesting
listenToUser(String uid) {
}

Then you can do when(cubit.listenToUser(any)).thenThrow(Exception())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM