testBloc<B extends BlocBase<State>, State> function

  1. @visibleForTesting
Future<void> testBloc<B extends BlocBase<State>, State>({
  1. required B build(),
  2. FutureOr<void> setUp()?,
  3. State seed()?,
  4. dynamic act(
    1. B bloc
    )?,
  5. Duration? wait,
  6. int skip = 0,
  7. dynamic expect()?,
  8. dynamic verify(
    1. B bloc
    )?,
  9. dynamic errors()?,
  10. FutureOr<void> tearDown()?,
})

Internal blocTest runner which is only visible for testing. This should never be used directly -- please use blocTest instead.

Implementation

@visibleForTesting
Future<void> testBloc<B extends BlocBase<State>, State>({
  required B Function() build,
  FutureOr<void> Function()? setUp,
  State Function()? seed,
  dynamic Function(B bloc)? act,
  Duration? wait,
  int skip = 0,
  dynamic Function()? expect,
  dynamic Function(B bloc)? verify,
  dynamic Function()? errors,
  FutureOr<void> Function()? tearDown,
}) async {
  var shallowEquality = false;
  final unhandledErrors = <Object>[];
  final localBlocObserver =
      // ignore: deprecated_member_use
      BlocOverrides.current?.blocObserver ?? Bloc.observer;
  final testObserver = _TestBlocObserver(
    localBlocObserver,
    unhandledErrors.add,
  );
  Bloc.observer = testObserver;

  try {
    await _runZonedGuarded(() async {
      await setUp?.call();
      final states = <State>[];
      final bloc = build();
      // ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member
      if (seed != null) bloc.emit(seed());
      final subscription = bloc.stream.skip(skip).listen(states.add);
      try {
        await act?.call(bloc);
      } catch (error) {
        if (errors == null) rethrow;
        unhandledErrors.add(error);
      }
      if (wait != null) await Future<void>.delayed(wait);
      await Future<void>.delayed(Duration.zero);
      await bloc.close();
      if (expect != null) {
        final dynamic expected = await expect();
        shallowEquality = '$states' == '$expected';
        try {
          test.expect(states, test.wrapMatcher(expected));
        } on test.TestFailure catch (e) {
          if (shallowEquality || expected is! List<State>) rethrow;
          final diff = _diff(expected: expected, actual: states);
          final message = '${e.message}\n$diff';
          // ignore: only_throw_errors
          throw test.TestFailure(message);
        }
      }
      await subscription.cancel();
      await verify?.call(bloc);
      await tearDown?.call();
    });
  } catch (error) {
    if (shallowEquality && error is test.TestFailure) {
      // ignore: only_throw_errors
      throw test.TestFailure(
        '''
${error.message}
WARNING: Please ensure state instances extend Equatable, override == and hashCode, or implement Comparable.
Alternatively, consider using Matchers in the expect of the blocTest rather than concrete state instances.\n''',
      );
    }
    if (errors == null || !unhandledErrors.contains(error)) {
      rethrow;
    }
  }

  if (errors != null) test.expect(unhandledErrors, test.wrapMatcher(errors()));
}