Home > Enterprise >  Flutter: bloc test problem with comparing expected and actual
Flutter: bloc test problem with comparing expected and actual

Time:07-03

I have tests like the below:

      blocTest(
        'emits [ViewData.loading and ViewData.loaded] when GetRepositories is added',
        build: () {
          when(
            () => useCase.getRepositories(),
          ).thenAnswer((_) async => Right(repositoriesDummyEntityFromRemote));
          return homeBloc;
        },
        act: (HomeBloc bloc) => bloc.add(GetRepositories()),
        expect: () => [
          HomeState(
            statusRepositories: ViewData.loading(message: 'Loading'),
            isShowTitle: false,
          ),
          HomeState(
            statusRepositories:
                ViewData.loaded(data: repositoriesDummyEntityFromRemote),
            isShowTitle: false,
          ),
        ],
      );

When I run get the error:

package:bloc_test/src/bloc_test.dart 229:13  testBloc.<fn>.<fn>
dart:async                                   _completeOnAsyncError
package:bloc_test/src/bloc_test.dart         testBloc.<fn>.<fn>
===== asynchronous gap ===========================
dart:async                                   _asyncThenWrapperHelper
package:bloc_test/src/bloc_test.dart         testBloc.<fn>.<fn>
dart:async                                   runZonedGuarded
package:bloc_test/src/bloc_test.dart 192:13  testBloc.<fn>
package:bloc_test/src/bloc_test.dart 191:5   testBloc.<fn>
dart:async                                   runZoned
package:bloc/src/bloc_overrides.dart 46:26   BlocOverrides.runZoned
package:bloc_test/src/bloc_test.dart 190:23  testBloc
package:bloc_test/src/bloc_test.dart 156:13  blocTest.<fn>
package:bloc_test/src/bloc_test.dart 155:5   blocTest.<fn>

Expected: [
            HomeState:HomeState(Instance of 'ViewData<List<RepositoriesEntity>>', false),
            HomeState:HomeState(Instance of 'ViewData<List<RepositoriesEntity>>', false)
          ]
  Actual: [
            HomeState:HomeState(Instance of 'ViewData<List<RepositoriesEntity>>', false),
            HomeState:HomeState(Instance of 'ViewData<List<RepositoriesEntity>>', false)
          ]
   Which: at location [0] is HomeState:<HomeState(Instance of 'ViewData<List<RepositoriesEntity>>', false)> instead of HomeState:<HomeState(Instance of 'ViewData<List<RepositoriesEntity>>', false)>

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.

repositoriesDummyEntityFromRemote is List<RepositoriesEntity>

Please help me to solve my test. Below is my Bloc, State, and ViewData.

ViewData

class ViewData<T> {
  ViewState status;
  T? data;
  String message = "";
  Failure? failure;

  ViewData._({
    required this.status,
    this.data,
    this.message = "",
    this.failure,
  });

  factory ViewData.loaded({T? data}) {
    return ViewData._(status: ViewState.loaded, data: data);
  }

  factory ViewData.error({required Failure? failure}) {
    return ViewData._(status: ViewState.error, failure: failure);
  }

  factory ViewData.loading({required String message}) {
    return ViewData._(status: ViewState.loading, message: message);
  }

  factory ViewData.initial() {
    return ViewData._(status: ViewState.initial);
  }

  factory ViewData.empty({required String message}) {
    return ViewData._(status: ViewState.empty, message: message);
  }
}

HomeState

class HomeState extends Equatable {
  final ViewData<List<RepositoriesEntity>> statusRepositories;
  final bool isShowTitle;

  const HomeState({
    required this.statusRepositories,
    required this.isShowTitle,
  });

  HomeState copyWith({
    ViewData<List<RepositoriesEntity>>? statusRepositories,
    bool? isShowTitle,
  }) {
    return HomeState(
      statusRepositories: statusRepositories ?? this.statusRepositories,
      isShowTitle: isShowTitle ?? this.isShowTitle,
    );
  }

  @override
  List<Object?> get props => [statusRepositories, isShowTitle];
}

HomeBloc

class HomeBloc extends Bloc<HomeEvent, HomeState> {
  final GTHomeUseCase homeUseCase;

  HomeBloc({
    required this.homeUseCase,
  }) : super(HomeState(
          statusRepositories: ViewData.initial(),
          isShowTitle: false,
        )) {
    on<GetRepositories>(_getRepositories);
  }

  Future<void> _getRepositories(
    GetRepositories event,
    Emitter<HomeState> emit,
  ) async {
    emit(state.copyWith(
        statusRepositories: ViewData.loading(message: 'Loading')));

    final response = await homeUseCase.getRepositories();

    return response.fold(
      (Failure failure) => _onFailureRepositories(emit, failure),
      (List<RepositoriesEntity> data) => _onSuccessRepositories(emit, data),
    );
  }

  Future<void> _onFailureRepositories(
    Emitter<HomeState> emit,
    Failure failure,
  ) async {
    emit(state.copyWith(statusRepositories: ViewData.error(failure: failure)));
  }

  Future<void> _onSuccessRepositories(
    Emitter<HomeState> emit,
    List<RepositoriesEntity> data,
  ) async {
    emit(state.copyWith(statusRepositories: ViewData.loaded(data: data)));
    await Future.delayed(const Duration(milliseconds: 500));
    emit(state.copyWith(isShowTitle: true));
  }
}

Anyone know how to fix my bloc so I can make it testable?

CodePudding user response:

I think ViewData and RepositoriesEntity must extend Equatable, override == and hashCode, or implement Comparable.

If they are not, then there is no way of comparing the states.

  • Related