Getting 'pumpAndSettle timed out' error during my Widget Test using Bloc

45 views Asked by At

Scenario

I have a CustomButton, which when tapped should trigger a LoginEvent. I want to widget test my UI and LoginBloc. The following is my widget test code:

Code

testWidgets('Should show LoaderRow when state is loading', (tester) async {
    // Arrange
    when(() => mockLoginBloc.state).thenReturn(LoginLoading());

    // Act
    await tester.pumpWidget(const MainApp());
    // await tester.pumpWidget(initialWidget);
    await tester.pumpWidget(_makeTestableWidget(const LoginPage()));

    await tester.enterText(
        find.byKey(const ValueKey('EmailAddress')), '[email protected]');
    await tester.enterText(find.byKey(const ValueKey('Password')), 'Test@123');

    expect(find.byKey(const ValueKey('Login')), findsOneWidget);
    await tester.tap(find.byKey(const ValueKey('Login')));

    await tester.pumpAndSettle();
    // await tester.pump();
    // for (int i = 0; i < 5; i++) {
    //   await tester.pump(const Duration(seconds: 1));
    // }

    // Assert
    verify(() => mockLoginBloc.add(LoginAttempt(loginRequest: tLoginRequest)))
        .called(1);
    expect(find.byType(LoaderRow), findsOneWidget);
  });

Here, LoaderRow is a SpinKitFadingCircle taken from https://pub.dev/packages/flutter_spinkit

Problem

When I run the test above I encounter the following error which fails my test:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════ The following assertion was thrown running a test: pumpAndSettle timed out

Upon searching for solutions to this error on SO, I tried replacing pumpAndSettle with pump or even placing pump inside a loop, but that yielded me with yet another error:

The following TestFailure was thrown running a test: No matching calls. (If you called verify(...).called(0);, please instead use verifyNever(...);.)

My Bloc, State and Event related code are as follows:

LoginBloc

class LoginBloc extends Bloc<LoginEvent, LoginState> {
  final GetLoginDetails _getLoginDetails;

  LoginBloc(this._getLoginDetails) : super(LoginInitial()) {
    on<LoginAttempt>((event, emit) async {
      final loginRequest = event.loginRequest;

      emit(LoginLoading());

      final result = await _getLoginDetails.execute(loginRequest);
      result.fold(
        (failure) {
          emit(LoginError(failure.message));
        },
        (data) {
          emit(LoginSuccess(data));
        },
      );
    }, transformer: debounce(const Duration(milliseconds: 250)));
  }

  EventTransformer<T> debounce<T>(Duration duration) {
    return (events, mapper) => events.debounceTime(duration).flatMap(mapper);
  }
}

LoginEvent

abstract class LoginEvent extends Equatable {
  const LoginEvent();

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

class LoginAttempt extends LoginEvent {
  final Map<String, dynamic> loginRequest;

  const LoginAttempt({
    required this.loginRequest,
  });

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

LoginState

abstract class LoginState extends Equatable {
  const LoginState();

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

final class LoginInitial extends LoginState {}

final class LoginLoading extends LoginState {}

final class LoginSuccess extends LoginState {
  final Login result;

  const LoginSuccess(this.result);

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

final class LoginError extends LoginState {
  final String message;

  const LoginError(this.message);

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

Request

I would like to know what is wrong in my code that causes the test to fail and what changes I need to make to it to make the test pass.

0

There are 0 answers