user2142558
user2142558

Reputation: 157

Problems to create a unit test for http.post

I created this class to use http.post in dart:

class SigninDataSource {
  final http.Client client;

  SigninDataSource(this.client);

  Future<SignIn> signIn ({
    String email = '[email protected]',
    String password = 'test',
  }) async {
    var url = "https://test/test/signin";
    var body = json.decode('{"email": "$email", "password": "$password"}');

    final result = await client.post(url, body: json.encode(body), headers: {"content-type": "application/json",});
    print("Result");
    print(result);

    if(result.statusCode == 200) {
      SignIn.fromJson((result.body));
      return SignIn.fromJson(result.body);
    } else {
      throw SignInError(json.decode(result.body)['message']);
    }
  }
}

I was trying to create a unit test for it.

class MockClient extends Mock implements http.Client {}

void main() {
  String fixture(String name) => File('test/data/fixtures/$name.json').readAsStringSync();

  MockClient mockClient;
  SigninDataSource dataResource;

  setUp((){
    mockClient = MockClient();
    dataResource = SigninDataSource(mockClient);
  });

  group('signin', () {
    test(
      'return SignIn whrn the service call complete succesfully',
        () async {
          when(
            mockClient.post(
              "https://test/test/signin",
              body: '{"email": "[email protected]", "password": "Test@123"}',
              headers: {"content-type": "application/json"}
            )).thenAnswer(
              (_) async => http.Response('{"status": 200}', 200));
          expect(await dataResource.signIn(email: '[email protected]', password:'Test@123'),TypeMatcher<SignIn>());
        }
    );
  });
}

but i am getting this error:

Result
null

NoSuchMethodError: The getter 'statusCode' was called on null.
Receiver: null
Tried calling: statusCode

I think my mock method is not working but I cannot figure out what is the problem. I was checkoing this documentation https://flutter.dev/docs/cookbook/testing/unit/mocking I tried to replicate it for a http.post.Please, could someone with more experience help me to find the problem?

Upvotes: 0

Views: 2343

Answers (1)

Dustin Catap
Dustin Catap

Reputation: 431

The body parameter {"email": "[email protected]", "password": "Test@123"} in mockClient.post() during stubbing does not match the one being passed in client.post() in SigninDataSource.

If you check the string being passed in client.post()

From

final result = await client.post(url, body: json.encode(body), headers: {
  "content-type": "application/json",
});

to

var encodedBody = json.encode(body);

final result = await client.post(url, body: encodedBody, headers: {
    "content-type": "application/json",
});

The value of encodedBody is {"email":"[email protected]","password":"Test@123"}. Notice that there are no spaces.

You can also modify your stubbing to this if you want to disregard the value of the parameters being passed since you only need the success response. You will use anyNamed('paramName').

when(mockClient.post("https://test/test/signin",
        body: anyNamed('body'),
        headers: anyNamed('headers')))
    .thenAnswer((_) async => http.Response('{"status": 200}', 200));

Upvotes: 3

Related Questions