Dave
Dave

Reputation: 2018

Testing bloc events type 'Null' is not a subtype of type

I am trying to learn bloc and I am writing simple unit tests. I am trying to test the auth events but I am facing the error below. Inside my app when I trigger an event, I don't get any errors and everything seems to work fine, so why am I getting error here? Am I missing something, could anyone advise?

enter image description here

class AuthenticationBloc
    extends Bloc<AuthenticationEvent, AuthenticationState> {
  final AuthenticationRepository _authRepository;
  late StreamSubscription<AuthStatus> _authSubscription;

  AuthenticationBloc(
      {required AuthenticationRepository authenticationRepository})
      : _authRepository = authenticationRepository,
        super(const AuthenticationState()) {

    on<AuthStateChanged>(_onAuthStatusChanged);
    on<AuthenticationLogoutRequested>(_onLogoutRequested);

    _authSubscription = _authRepository.status
        .listen((status) => add(AuthStateChanged(authStatus: status)));
  }
enum AuthStatus { unknown, authenticated, unauthenticated }

class AuthenticationRepository {
  final _controller = StreamController<AuthStatus>();

  Stream<AuthStatus> get status => _controller.stream;

  Future<void> logIn({
    required String username,
    required String password,
  }) async {
    await Future.delayed(
      const Duration(milliseconds: 300),
      () => _controller.add(AuthStatus.authenticated),
    );
  }

  void logOut() {
    _controller.add(AuthStatus.unauthenticated);
  }

  void dispose() => _controller.close();
}

class AuthenticationState extends Equatable {
  final AuthStatus status;
  final User? user;

  const AuthenticationState({this.status = AuthStatus.unknown, this.user});

  @override
  List<Object?> get props => [user, status];
}
void main() {
  late AuthenticationBloc authenticationBloc;

  MockAuthenticationRepository authenticationRepository = MockAuthenticationRepository();

  setUp((){
    authenticationBloc = AuthenticationBloc(authenticationRepository: authenticationRepository);
  });

  group('AuthenticationEvent', () {
    group('Auth status changes', () {
      test('User is unknown', () {
        expect(authenticationBloc.state.status, AuthStatus.unknown);
      });

      test('User is authorized', () {
        authenticationBloc.add(AuthStateChanged(authStatus: AuthStatus.authenticated));
        expect(authenticationBloc.state.status, AuthStatus.authenticated);
      });

      test('User is unauthorized', () {
        authenticationBloc.add(AuthStateChanged(authStatus: AuthStatus.unauthenticated));
        expect(authenticationBloc.state.status, AuthStatus.unknown);
      });
    });


  });
}

Upvotes: 3

Views: 1714

Answers (1)

potatoCutts
potatoCutts

Reputation: 196

It is most likely that you have not created a stub for a function in your mock class. This is generally the cause of the NULL return. This can be achieved by using when() from the mockito package. https://pub.dev/packages/mockito.

Also there is a bloc testing package that may be useful to look into. https://pub.dev/packages/bloc_test

Below is an example of how I implemented it. Hope this helps.

blocTest<ValidateUserBloc, ValidateUserState>('Validate User - Success',
    build: () {
      when(mockSettingsRepo.validateUser(url, authCode)).thenAnswer(
          (_) async => User(
              success: true, valid: true, url: url, authCode: authCode));
      return validateUserBloc;
    },
    seed: () => ValidateUserState(user: User(url: url, authCode: authCode)),
    act: (bloc) => bloc.add(ValidateUserAuthoriseEvent()),
    expect: () => <ValidateUserState>[
          ValidateUserState(
              status: ValidUserStatus.success,
              user: User(
                  success: true, valid: true, url: url, authCode: authCode))
        ]);

Upvotes: 4

Related Questions