Как стать автором
Обновить

Комментарии 1

он будет создаваться всего один раз. А вот сам BLoC мы будет создавать для каждого теста единожды.

```

LoginRepository repository; LoginBloc bloc; setUp(() { repository = MockLoginRepository(); bloc = LoginBloc(repository); });

```

Текст не соответствует коду? В коде и репозиторий и блок создаются для каждого теста. При этом этот код еще и не соответствует коду в гитхабе.

final String? email;

final String? password;

Эти поля повторяются в трех классах? Может быть стоило вынести в какой-то базовый класс? Или миксин? В таком случае код геттера emailStr можно было бы значительно сократить. Еще момент в том, что во всех состояниях эти поля зануляемые, что странно. Блок как раз и славится тем, что позволяет безболезненно моделировать точные состояния.

extension LoginStateX on LoginState { String? get emailStr { if (this is LoginInitialState || this is LoginSuccessState) { return null; } else if (this is LoginDataState) { return (this as LoginDataState).email; } else if (this is LoginLoadingState) { return (this as LoginLoadingState).email; } else if (this is LoginErrorState) { return (this as LoginErrorState).email; } return null; } }

Конечно вкусовщина, но возможно стоило не создавать расширение, а перенести этот геттер прямо в класс `LoginState`? Кстати, если сохранить this в локальную переменную, то не придется писать `as LoginDataState`.

act: (_bloc) => _bloc.add(EditedEmail('example@sample.com')),

Обычно для параметров и локальных переменных не используется знак подчеркивания _ в названии, так как они и так приватные.

blocTest( 'emits [LoginDataState] after adding email', build: () => bloc, act: (_bloc) => _bloc.add(EditedEmail('example@sample.com')), expect: () => [ isA<LoginDataState>(), ], );

Разве проверки одного только типа состояния достаточно? А вдруг в нем измененный эмейл не сохранится? Или сохранится не тот? Аналогично и в следующем тесте. Вдруг изменение пароля повлияло на ранее сохраненный эмейл?

Тут мы использовали еще одно свойство blocTest - seed, которое нужно для подстановки изначального состояния в BLoC.

Как то использование seed выглядит не очень уместным и даже опасным. По хорошему обычно изолируют зависимости, а в логику тестируемого класса извне не лезут. Другими словами лучше взаимодействовать с тестируемой сущностью только доступными публичными методами. Так как сделано ниже.

blocTest( 'emits [LoginErrorState] if email is null', build: () => bloc, act: (_bloc) { _bloc.add(EditedPassword('myPass123')); _bloc.add(LoginButtonPressed()); }, expect: () => [ isA<LoginDataState>(), isA<LoginLoadingState>(), isA<LoginErrorState>(), ], );

По идее `_bloc.add(EditedPassword('myPass123'));` должно быть в build, так как это относится к части arrange.

Если мы внимательно посмотрим на код, то увидим, что нужно протестировать следующие кейсы:

Наверное так же стоило проверить случаи когда пароль и/или логин неправильные?

Запустил тесты из репозитория, но один не проходит:

package:matcher                              expect
package:mocktail/src/mocktail.dart 595:5     VerificationResult.called
test\auth_bloc\login_bloc_test.dart 93:18    main.<fn>.<fn>
package:bloc_test/src/bloc_test.dart 230:21  testBloc.<fn>
===== asynchronous gap ===========================
dart:async                                   _Completer.completeError
package:bloc_test/src/bloc_test.dart 257:43  _runZonedGuarded.<fn>
===== asynchronous gap ===========================
dart:async                                   _CustomZone.registerBinaryCallback
package:bloc_test/src/bloc_test.dart 254:5   _runZonedGuarded.<fn>
dart:async                                   runZonedGuarded
package:bloc_test/src/bloc_test.dart 253:3   _runZonedGuarded
package:bloc_test/src/bloc_test.dart 200:11  testBloc
package:bloc_test/src/bloc_test.dart 156:13  blocTest.<fn>

Expected: <1>
  Actual: <3>
Unexpected number of calls

Печалька...

if (state.emailStr?.isNotEmpty == false || state.emailStr?.isNotEmpty == false) { emit(LoginErrorState( email: state.emailStr, password: state.passwordStr, errorToShow: 'Email or password is empty', )); return; }

Дважды на пустоту проверяется email, а пароль нет? Странно, что ваши тесты это не отловили. Возможно вам стоит посмотреть в сторону TDD?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории