简体   繁体   中英

Flutter: http.client always returns null

I'm applying a unit test over a http request in a Flutter application using Mockito.

Code to be tested:

abstract class LoginRemoteDataSource {
  Future<LoginModel> login(String email, String password);
}

class LoginRemoteDataSourceImplementation implements LoginRemoteDataSource {
  http.Client client;

  LoginRemoteDataSourceImplementation({@required this.client});

  @override
  Future<LoginModel> login(String email, String password) async {
    // httpClient
    final response = await client.post(
        Uri.http("localhost:80", "/api/v1/auth/login"),
        headers: <String, String>{
          'Content-type': 'application/json; charset=UTF-8'
        },
        body:
            jsonEncode(<String, String>{'email': email, 'password': password}));
    print(response);
    return LoginModel.fromJson(json.decode(response.body));
  }
}

response is always null !!

when I'm changing the client.post to http.post it works and returns the expected result

I'm applying something very similar to this https://flutter.dev/docs/cookbook/testing/unit/mocking

I doubted that the issue due to the localhost. but I tried a simple get request over a placeholder api for a testing response purposes https://jsonplaceholder.typicode.com and also it returns null.

Why I'm getting the null response? why the client.post is not working?

UPDATE

I noticed that the issue is not from the above code, it seems from the testing part.

class MockHttpClient extends Mock implements http.Client {}
void main() {
  LoginRemoteDataSourceImplementation loginRemoteDataSourceImplementation;
  LoginModel testingLoginModel;
  MockHttpClient mockHttpClient;


  setUp(() {
    mockHttpClient = MockHttpClient();
    loginRemoteDataSourceImplementation =
        LoginRemoteDataSourceImplementation(client: mockHttpClient);
testingLoginModel =
    LoginModel.fromJson(json.decode(fixture('login_fixture.json')));
  });


test("Should return login model when the request code is 200", () async {
  // arrange
  when(mockHttpClient.post(any, headers: anyNamed('headers'))).thenAnswer(
      (_) async => http.Response(fixture('login_fixture.json'), 200));
  // act
  final result = await loginRemoteDataSourceImplementation.login(
      'testingEmail', 'testingPassword');

  // assert
  expect(result, equals(testingLoginModel));
}, tags: 'login');
}

Mockito version is ^5.0.5

update this:

abstract class LoginRemoteDataSource {
  Future<LoginModel> login(String email, String password);
}

class LoginRemoteDataSourceImplementation implements LoginRemoteDataSource {
  http.Client client = http.Client(); //<-- update

  LoginRemoteDataSourceImplementation(); //<-- update

  @override
  Future<LoginModel> login(String email, String password) async {
    // httpClient
    final response = await client.post(
        Uri.http("localhost:80", "/api/v1/auth/login"),
        headers: <String, String>{
          'Content-type': 'application/json; charset=UTF-8'
        },
        body:
            jsonEncode(<String, String>{'email': email, 'password': password}));
    print(response);
    return LoginModel.fromJson(json.decode(response.body));
  }
}

That problem was due the Mockito version, I was applying an old approach.

Then new one is exactly the as the https://flutter.dev/docs/cookbook/testing/unit/mocking by generating a new mock file thats creates a mock class extends the mock and implement the http.client using the builder_runner package.

using the @GenerateMocks([http.Client]) annotation before the main function is important

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM