如何在 Flutter 中测试密封状态类?

Lui*_*era 7 unit-testing flutter bloc freezed

我正在使用 Freezed 在我的 Flutter 应用程序中生成密封数据类。我需要测试它,但我不知道该怎么做。任何想法?这是状态:

@freezed
abstract class LoginState with _$LoginState {
  const factory LoginState({
    @required Email email,
    @required Password password,
    @required bool isLoading,
    @required bool showErrors,
    @required Option<Either<AuthFailure, Unit>> failureOrSuccessOption,
  }) = _LoginState;

  factory LoginState.initial() => LoginState(
        failureOrSuccessOption: none(),
        isLoading: false,
        showErrors: false,
        email: Email(''),
        password: Password(''),
      );
}
Run Code Online (Sandbox Code Playgroud)

这是我一直在尝试运行的测试:

import 'package:dartz/dartz.dart';
import 'package:exchangecontrol/auth/application/login_cubit/login_cubit.dart';
import 'package:exchangecontrol/auth/domain/auth_repository.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter_test/flutter_test.dart';

class MockLoginWithEmailAndPassword extends Mock implements AuthRepository {}

void main() {
  LoginCubit loginCubit;
  MockLoginWithEmailAndPassword mockLoginWithEmailAndPassword;

  setUp(() {
    mockLoginWithEmailAndPassword = MockLoginWithEmailAndPassword();
    loginCubit = LoginCubit(mockLoginWithEmailAndPassword);
  });
  test('Should be able to test login', () async {
    when(mockLoginWithEmailAndPassword.loginWithEmailAndPassword(any, any))
        .thenAnswer((_) async => right(unit));
    loginCubit.loginButtonPressed();
    expectLater(
      loginCubit,
      emitsInOrder(
        [
          loginCubit.state.copyWith(isLoading:true),
          loginCubit.state.copyWith(isLoading:false),
        ],
      ),
    );
  });
}
Run Code Online (Sandbox Code Playgroud)

我想检查在执行 cubit loginMethod 时,它是否正确地将加载状态更改为 true(在获取结果时)和 false(获取结果后),但我收到此错误消息:

Expected: should do the following in order:
          * emit an event that _$_LoginState:<LoginState(email: Value(Left(EmailFailure.empty())), password: Value(Left(PasswordFailure.empty())), isLoading: true, showErrors: false, failureOrSuccessOption: None)>
          * emit an event that _$_LoginState:<LoginState(email: Value(Left(EmailFailure.empty())), password: Value(Left(PasswordFailure.empty())), isLoading: false, showErrors: false, failureOrSuccessOption: None)>
  Actual: _$_LoginState:<LoginState(email: Value(Left(EmailFailure.empty())), password: Value(Left(PasswordFailure.empty())), isLoading: false, showErrors: false, failureOrSuccessOption: None)>
   Which: was not a Stream or a StreamQueue
Run Code Online (Sandbox Code Playgroud)

Mar*_*lio 0

您可以使用 bloc_test 它具有用于测试块的特定功能

下面的代码片段来自我试图通过测试完成的 flutter 应用程序/教程。下面的代码对我有用。



    part of 'sign_in_form_bloc.dart';
    
    @freezed
    class SignInFormState with _$SignInFormState {
      const factory SignInFormState({
        required EmailAddress email,
        required Password password,
        required bool showErrorMessages,
        required bool isSubmitting,
        required Option> authFailureOrSuccessOption,
      }) = _SignInFormState;
    
      factory SignInFormState.initial() => SignInFormState(
            email: EmailAddress(''),
            password: Password(''),
            showErrorMessages: false,
            isSubmitting: false,
            authFailureOrSuccessOption: none(),
          );
    }

Run Code Online (Sandbox Code Playgroud)

... this is part of the test file ...
    group('on SignInFormEvent.signInWithGooglePressed', () {
          blocTest(
              'emits submitting in progress first, then emits success, when signInWithGoogle succeeds',
              setUp: () {
                when(() => mockAuthFacade.signInWithGoogle())
                    .thenAnswer((_) async => right(unit));
              },
              build: () => SignInFormBloc(mockAuthFacade),
              act: (bloc) =>
                  bloc.add(const SignInFormEvent.signInWithGooglePressed()),
              expect: () => [
                    SignInFormState.initial().copyWith(
                      isSubmitting: true,
                      authFailureOrSuccessOption: none(),
                    ),
                    SignInFormState.initial().copyWith(
                      isSubmitting: false,
                      authFailureOrSuccessOption: some(right(unit)),
                    ),
                  ]);
          blocTest(
              'emits submitting in progress first, then emits failure, when signInWithGoogle fails',
              setUp: () {
                when(() => mockAuthFacade.signInWithGoogle()).thenAnswer(
                    (_) async => left(const AuthFailure.cancelledByUser()));
              },
              build: () => SignInFormBloc(mockAuthFacade),
              act: (bloc) =>
                  bloc.add(const SignInFormEvent.signInWithGooglePressed()),
              expect: () => [
                    SignInFormState.initial().copyWith(
                      isSubmitting: true,
                      authFailureOrSuccessOption: none(),
                    ),
                    SignInFormState.initial().copyWith(
                      isSubmitting: false,
                      authFailureOrSuccessOption:
                          some(left(const AuthFailure.cancelledByUser())),
                    ),
                  ]);
        });
...
Run Code Online (Sandbox Code Playgroud)