Home > Enterprise >  Flutter Bloc Unit Test return an empty array
Flutter Bloc Unit Test return an empty array

Time:12-24

I'm trying to make a unit test using the bloc_test library.

Here are my codes.

Login Cubit

class LoginCubit extends Cubit<LoginState> with HydratedMixin {
  final UserRepository _userRepository;
  LoginCubit(this._userRepository) : super(LoginInitial());

  Future<void> login (String email, String password , bool remember) async {
    bool result = await _userRepository.isLoginCorrectWithEmailAndPassword(email, password);
    if (result){
      emit(LoggedIn(remember: remember, email: email));
    } else {
      emit(LoginError());
    }
  }
}

Login States

part of 'login_cubit.dart';

@immutable
abstract class LoginState extends Equatable {}

class LoginInitial extends LoginState {
  final bool remember;
  final String email;
  LoginInitial({this.remember = false, this.email = ''});

  @override
  List<Object?> get props => [remember, email];
}

class LoggedIn extends LoginState {
  final bool remember;
  final String email;
  LoggedIn({required this.remember, required this.email});

  @override
  List<Object?> get props => [remember, email];
}

class LoginError extends LoginState {
  LoginError();

  @override
  List<Object?> get props => [];
}

Unit Test

class MockUserRepository extends Mock implements UserRepository {
  @override
  Future<bool> isLoginCorrectWithEmailAndPassword(String email, String password) {
    return Future.value(true);
  }
}

void main() {
  group('LoginCubit', () {
    late LoginCubit loginCubit;

    setUp(() {
      loginCubit = LoginCubit(MockUserRepository());
    });

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

    test('the initial state value is LoginInitial', () {
      expect(loginCubit.state, LoginInitial());
    });

    blocTest<LoginCubit, LoginState>(
      'TODO: description',
      build: () => loginCubit,
      act: (cubit) => cubit.login("any email", "any password", true),
      expect: () => <LoginState>[
        LoggedIn(remember: true, email: "any email"),
      ],
    );
  });
}

My issue is that the second test return always an empty array. With some prints, I'm sure that the code is emitting the LoggedIn states but the test actually don't recognize it.

Where did I make a mistake ? :)

CodePudding user response:

You forgot to add the stub for the repository function call.

  1. Create an Object from the Mock Class MockUserRepository repo = MockUserRepository();

  2. Pass this object to the LoginCubit in the setUp function like this

    setUp(() { loginCubit = LoginCubit(repo); });

  3. Add this line to the act function in the test

        when(repo.isLoginCorrectWithEmailAndPassword(any, any)).thenAnswer((_) async => true);
    

so the whole test should be like this

blocTest<LoginCubit, LoginState>(
  'TODO: description',
  build: () => loginCubit,
  act: (cubit) {
      when(repo.isLoginCorrectWithEmailAndPassword(any, any)).thenAnswer((_) async => true);
      cubit.login("any email", "any password", true);
  },
  expect: () => <LoginState>[
    LoggedIn(remember: true, email: "any email"),
  ],
);

CodePudding user response:

The issue was that I was using an Hydrated Bloc without initializing it in the test. Here's the solution to it : https://github.com/felangel/bloc/issues/2022#issuecomment-747918417

  • Related