【问题标题】:How to deal with "Assertion error is not a subtype of of type 'Exception' in type cast如何处理“断言错误不是类型转换中'异常'类型的子类型
【发布时间】:2022-07-04 15:01:48
【问题描述】:

当我的测试失败时,我在尝试在我的项目中实现 blocTesting 时遇到了一个奇怪的错误。如下:

Expected: [
            SignUpCreateAccountLoading:SignUpCreateAccountLoading(),
            SignupInitial:SignupInitial()
          ]
  Actual: [
            SignUpCreateAccountLoading:SignUpCreateAccountLoading(),
            SignUpCreateAccountFailure:SignUpCreateAccountFailure(type '_AssertionError' is not a subtype of type 'Exception' in type cast, nikunj@gmail.com),
            SignupInitial:SignupInitial()
          ]

我需要在这个项目的 bloc 测试中使用真正的 api。

以下是 blocTest、bloc、blocEvent、blocState 和存储库文件。

SignupBlocTest


void main() async {
  group('SignupBloc', () {
    late SignUpBloc signUpBloc;
    setUp(() {
      signUpBloc = SignUpBloc();
    });

    test('initial state of the bloc is [AuthenticationInitial]', () {
      expect(SignUpBloc().state, SignupInitial());
    });

    group('SignUpCreateAccount', () {
      blocTest<SignUpBloc, SignUpState>(
        'emits [SignUpCreateAccountLoading, SignupInitial] '
        'state when successfully Signed up',
        setUp: () {},
        build: () => SignUpBloc(),
        act: (SignUpBloc bloc) => bloc.add(const SignUpCreateAccount(
            'Nevil', 'abcd', 'nikunj@gmail.com', 'english',),),
        wait: const Duration(milliseconds: 10000),
        expect: () => [
          SignUpCreateAccountLoading(),
          SignupInitial(),
        ],
      );
    });
  });
}

signupBloc

class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
  final SignUpRepository _signUpRepository = SignUpRepository();

  SignUpBloc() : super(SignupInitial()) {
    // Register events here
    on<SignUpCreateAccount>(_onSignUpCreateAccount);
  }

  Future<void> _onSignUpCreateAccount(SignUpCreateAccount event, Emitter<SignUpState> emit) async {
    emit(SignUpCreateAccountLoading());
    try {
      final bool _success = await _signUpRepository.createAccount(event.firstName, event.lastName, event.eMailAddress, event.language);

      if (_success) emit(SignUpCreateAccountSuccess());
    } catch (e) {
      emit(SignUpCreateAccountFailure(exception: e.toString(), email: event.eMailAddress));
      emit(SignupInitial());
    }
  }
}

Signup_event

part of 'signup_bloc.dart';

abstract class SignUpEvent extends Equatable {
  const SignUpEvent();

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

class SignUpCreateAccount extends SignUpEvent {
  final String firstName;
  final String lastName;
  final String eMailAddress;
  final String language;

  const SignUpCreateAccount(this.firstName, this.lastName, this.eMailAddress, this.language);
  @override
  List<Object> get props => <Object>[firstName, lastName, eMailAddress, language];
}

注册状态

part of 'signup_bloc.dart';

abstract class SignUpState extends Equatable {
  const SignUpState();

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

class SignupInitial extends SignUpState {}

class SignUpCreateAccountLoading extends SignUpState {}

class SignUpCreateAccountSuccess extends SignUpState {}

class SignUpCreateAccountFailure extends SignUpState {
  final String exception;
  final String email;

  const SignUpCreateAccountFailure({required this.exception, required this.email});
  @override
  List<Object> get props => <Object>[exception, email];
}

注册存储库

class SignUpRepository {
  Future<bool> createAccount(String _firstName, String _lastName, String _eMailAddress, String _language) async {
    final Response _response;
    try {
      _response = await CEApiRequest().post(
        Endpoints.createCustomerAPI,
        jsonData: <String, dynamic>{
          'firstName': _firstName,
          'lastName': _lastName,
          'email': _eMailAddress,
          'language': _language,
          'responseUrl': Endpoints.flutterAddress,
        },
      );

      final Map<String, dynamic> _customerMap = jsonDecode(_response.body);
      final CustomerModel _clients = CustomerModel.fromJson(_customerMap['data']);

      if (_clients.id != null) {
        return true;
      } else {
        return false;
      }
    } catch (e) {
      final KBMException _exception = e as KBMException;
      throw _exception;
    }
  }
}

【问题讨论】:

  • 1.为什么要捕获所有内容而不是仅捕获 KBMExceptions?您正在掩盖其他故障(在您的情况下,AssertionError 及其堆栈跟踪)。 2. 如果要重新抛出异常,请使用rethrow 来保留堆栈跟踪。 3. 你为什么要重新抛出异常?如果您捕获异常只是为了重新抛出它,请不要首先捕获它。完全摆脱trycatch
  • @jamesdlin 如果我根本不使用 try catch 如何捕获错误。您还认为以下 danharms 的回答是否有意义?我试过了,它看起来更好,但不确定我是否应该删除整个 try catch 的东西
  • 你用catch捕捉东西,但是1.you usually shouldn't catch everything,2.you usually shouldn't catch Errors。如所写,您的 catch 块是毫无意义的,因为它只是重新抛出异常,如果您根本没有捕获任何东西,就会发生同样的事情。更糟糕的是,它是有害的,因为不正确的演员表引入了一个额外的失败点,掩盖了其他错误

标签: flutter flutter-test


【解决方案1】:

_AssertionError 正在某处被抛出,但您正试图将其转换为 catch 中的异常。相反,您应该重新抛出您期望的异常并以不同的方式处理其他类型。下面我返回 false,但您可以选择适合您需要的行为。

try {
  ...
} on KBMException catch (e) {
  rethrow;
} catch (e) {
  // Not a KBMException so returning false.
  return false;
}

【讨论】:

  • rethrowthrow e 更好,因为它将保留原始堆栈跟踪。覆盖catch 块(缺少catch 关键字)是一个坏主意,因为它会默默地吞下并掩盖其他错误(例如AssertionError)。最好完全忽略它(此时捕获和重新抛出KBMException 也变得毫无意义;try-catch 都可以消失)。
  • 谢谢我更新了。答案的目的是指出问题所在并展示区分类型的方法。如果他们不需要这个,他们可以按照你的建议去做。
猜你喜欢
  • 2021-01-17
  • 2021-09-22
  • 2021-06-22
  • 2021-10-19
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 2021-11-28
  • 2019-08-03
相关资源
最近更新 更多