Ricbermo
Ricbermo

Reputation: 805

How to mock Riverpod's Reader?

I have the following repository and I'd like to test it. I know this may be a silly question but I'm still learning.

class AuthRepository implements AuthBaseRepository {
  final Reader _read;

  const AuthRepository(this._read);

  @override
  Future<User> login({String email, String password}) async {
    try {
      final response = await _read(dioProvider).post(
        '/sign_in',
        data: {
          "user": {
            "email": email,
            "password": password,
          },
        },
      );
      return _mapUserFromResponse(response);
    } on DioError catch (_) {
      throw const CustomException(message: 'Invalid login credentials.');
    } on SocketException catch (_) {
      const message = 'Please check your connection.';
      throw const CustomException(message: message);
    }
  }

And this is what I've done so far:


void main() {
  test('loadUser', () async {
    Dio dio;
    DioAdapterMockito dioAdapterMockito;
    AuthRepository repository;

    setUpAll(() {
      dio = Dio();
      dioAdapterMockito = DioAdapterMockito();
      dio.httpClientAdapter = dioAdapterMockito;
      repository = AuthRepository(_reader_here_);
    });

    test('mocks any request/response via fetch method', () async {
      final responsePayload =
          await parseJsonFromAssets("assets/api-response.json");

      final responseBody = ResponseBody.fromString(
        responsePayload,
        200,
        headers: {
          Headers.contentTypeHeader: [Headers.jsonContentType],
        },
      );

      when(dioAdapterMockito.fetch(any, any, any))
          .thenAnswer((_) async => responseBody);
    });
  });
}

I have no idea of how to mock Reader. Basically, I've seen something like class MyMock extends Mock implements Something but Reader is not a class, it's a function so I'm completely lost.

Any help/tips/examples will be appreciated.

Thanks in advance!

Upvotes: 1

Views: 1598

Answers (1)

Alex Hartford
Alex Hartford

Reputation: 6000

Instead of trying to mock a Reader, create a provider for your repository and use ProviderContainer to read it.

class AuthRepository implements AuthBaseRepository {
  const AuthRepository(this._read);

  static final provider = Provider<AuthRepository>((ref) => AuthRepository(ref.read));

  final Reader _read;

  @override
  Future<User> login({String email, String password}) async {
    ...
  }

Example usage:

final user = createTestUser();

final container = ProviderContainer(
  overrides: [
    // Example of how you can mock providers
    dio.overrideWithProvider(mockDio),
  ],
);

final repo = container.read(AuthRepository.provider);

expectLater(
  await repo.login(email: 'AzureDiamond', password: 'hunter2'),
  user,
);

You could also consider using the overrides in ProviderContainer to mock Dio instead of involving a mocking framework to simplify your tests further.

More on testing here.

Upvotes: 8

Related Questions