type 'Null' is not a subtype of type 'Future<List<Job>> when unit testing a throw

41 Views Asked by At

i'm trying to unit test a method in my BLoC but i'm encountering a strange error:

No matching calls. All calls: MockAlertBloc.add(AlertError(type 'Null' is not a subtype of type 'Future<List>', null)) (If you called verify(...).called(0);, please instead use verifyNever(...);.) package:matcher fail package:mocktail/src/mocktail.dart 728:7 _VerifyCall._checkWith package:mocktail/src/mocktail.dart 519:18 _makeVerify. test/blocs/job_bloc_test.dart main..

I debugged it and figured out it was throwed by the jobRepository.getJobs(), which makes no sense because I'm litterally mocking that method in my test.

Is there anything I'm doing wrong in here ?

My BLoC method:

  void _onFetch(JobFetch event, Emitter<JobState> emit) async {
    JobState oldState = state;
    try {
      emit(JobLoading());
      List<Job> jobs = await jobRepository.getJobs();
      emit(JobLoaded(jobs: jobs));
    } catch (e, stacktrace) {
      emit(oldState);
      alertBloc.add(AlertError(error: e, stackTrace: stacktrace));
    }
  }

and this is my test file:

class MockJobRepository extends Mock implements JobRepository {}

class MockAlertBloc extends MockBloc<AlertEvent, AlertState>
    implements AlertBloc {}

class MockAuthBloc extends MockBloc<AuthEvent, AuthState> implements AuthBloc {
  @override
  AuthState get state => AuthLoggedIn();
}

void main() {
  group('JobBloc', () {
    late JobRepository jobRepository;
    late AuthBloc authBloc;
    late AlertBloc alertBloc;
    late JobBloc jobBloc;

    setUp(() {
      jobRepository = MockJobRepository();
      authBloc = MockAuthBloc();
      alertBloc = MockAlertBloc();
      jobBloc = JobBloc(
        jobRepository: jobRepository,
        authBloc: authBloc,
        alertBloc: alertBloc,
      );
    });

    test('adds AlertError to AlertBloc when an error occurs during JobFetch',
        () async {
      final error = Exception('Error fetching jobs');

      when(() => jobRepository.getJobs()).thenThrow(error);

      final expectedStates = [
        JobInitial(), // Old state
      ];

      final expectedAlertError = AlertError(error: error, stackTrace: null);

      expectLater(
        jobBloc.stream,
        emitsInOrder(expectedStates),
      );

      verify(() => alertBloc.add(expectedAlertError)).called(1);

      jobBloc.add(const JobFetch());
    });
  });
}

If it can helps, this is my JobRepository

class JobRepository {
    final JobProvider jobProvider;

    const JobRepository({required this.jobProvider});

    Future<List<Job>> getJobs() async {
        List<Job> allJobs = await jobProvider.getJobs(query: {"perPage": "200"});
        allJobs.retainWhere((job) {
            bool? isPublished = job.isPublished;
            return isPublished != null &&
                isPublished &&
        });
        return allJobs;
    }
}

I tried to debug the test, tried to override the getJobs method in the MockJobRepository, to try to pass the test, but it wasn't helping

EDIT: Solution: I had to add the when(() => jobRepository.getJobs()).thenThrow(error); into the setup of test, because it wasn't working in the test directly for some reason

1

There are 1 best solutions below

9
pawelsa On

I think that error occurs as emitted AlertError is not the same as expectedAlertError. Try verify(alertBloc.add(isA<AlertError>())).called(1); if you want to check the argument of the error, you can use captureAny

final captured = verify(alertBloc.add(captureAny)).captured;
expect(captured.first.error, error);