Flutter Bloc 单元测试 return 一个空数组

Flutter Bloc Unit Test return an empty array

我正在尝试使用 bloc_test 库进行单元测试。

这是我的代码。

登录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());
    }
  }
}

登录状态

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 => [];
}

单元测试

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"),
      ],
    );
  });
}

我的问题是第二个测试 return 总是一个空数组。 通过一些打印,我确定代码正在发出 LoggedIn 状态,但测试实际上无法识别它。

我哪里弄错了? :)

您忘记为存储库函数调用添加存根。

  1. 从 Mock 创建对象 Class MockUserRepository repo = MockUserRepository();

  2. 像这样将这个对象传递给setUp函数中的LoginCubit

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

  3. 将这一行添加到测试中的act函数中

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

所以整个测试应该是这样的

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"),
  ],
);

问题是我在测试中使用了 Hydrated Bloc 而没有对其进行初始化。 这是它的解决方案: https://github.com/felangel/bloc/issues/2022#issuecomment-747918417