John Doe
John Doe

Reputation: 77

Flutter Test Error - type 'Null' is not a subtype of type 'Future<Response>'

I am trying to create a simple test but I keep getting this error.

type 'Null' is not a subtype of type 'Future'

test.dart

import 'package:flutter_test/flutter_test.dart';
import 'package:async/async.dart';
import 'package:http/http.dart' as http;
import 'package:mocktail/mocktail.dart';

class MockClient extends Mock implements http.Client {}

void main() {
  group('signin', () {
    final client = MockClient();
    final api = AuthApi('https://baseUrl', client);
    final credential = Credential(
      email: '[email protected]',
      type: AuthType.email,
      password: 'pass',
    );

    test('should return error when status code is not 200', () async {
      registerFallbackValue(Uri.parse(''));

      when(() => client.post(any(), body: {}))
          .thenAnswer((_) async => http.Response('{}', 404));

      final result = await api.signIn(credential);

      expect(result, isA<ErrorResult>());
    });
  });
}

Error is at line

final result = await api.signIn(credential); expect(result, isA());

If I remove those lines I don't see the error.

auth_api.dart

class AuthApi implements IAuthApi {
  AuthApi(this.baseUrl, this._client);

  final http.Client _client;
  String baseUrl;

  @override
  Future<Result<String>> signIn(Credential credential) async {
    final endpoint = Uri.parse(baseUrl + '/auth/signin');
    return await _postCredential(endpoint, credential);
  }

  @override
  Future<Result<String>> signUp(Credential credential) async {
    final endpoint = Uri.parse(baseUrl + '/auth/signup');
    return await _postCredential(endpoint, credential);
  }

  Future<Result<String>> _postCredential(
    Uri endpoint,
    Credential credential,
  ) async {
    final response =
        await _client.post(endpoint, body: Mapper.toJson(credential));
    if (response.statusCode != 200) {
      return Result.error('Server Error');
    }
    var json = jsonDecode(response.body);

    return json['auth_token'] != null
        ? Result.value(json['auth_token'])
        : Result.error(json['message']);
  }
}

I checked other similar question answers also but none of them worked. I am using mocktail package & http for post.

Upvotes: 1

Views: 4472

Answers (1)

pszklarska
pszklarska

Reputation: 206

The problem is in that line:

when(() => client.post(any(), body: {}))
  .thenAnswer((_) async => http.Response('{}', 404));

It means that when there's a client.post() method invoked with any() URL and a specific empty body {}, then it should return a mocked response.

What you want is to return a mocked response when there's any URL and any body, so it should be like this:

when(() => client.post(any(), body: any(named: 'body')))
  .thenAnswer((_) async => http.Response('{}', 404));

However, if you want to test if a specific error is thrown, that code should be modified:

test('should return error when status code is not 200', () async {

  when(() => client.post(any(), body: any(named: 'body')))
    .thenThrow(ErrorResult(Exception()));

  expect(() async => await api.signIn(credential),
    throwsA(isA<ErrorResult>()));
});

First, you specify that calling API should throw an error (when(...).thenThrow(...)) and then you check if an error was thrown (expect(..., throwsA(...)))

Upvotes: 1

Related Questions