颤振:http.client 总是返回 null

时间:2021-04-29 20:10:22

标签: flutter unit-testing http mockito

我正在使用 Mockito 对 Flutter 应用程序中的 http 请求应用单元测试。

待测试代码:

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));
  }
}

响应始终为空!!

当我将 client.post 更改为 http.post 时,它可以工作并返回预期的结果

我正在应用与此非常相似的东西https://flutter.dev/docs/cookbook/testing/unit/mocking

我怀疑是由于本地主机的问题。但我尝试通过占位符 api 进行简单的获取请求以测试响应目的 https://jsonplaceholder.typicode.com 并且它返回 null。

为什么我得到空响应?为什么 client.post 不起作用?

更新

我注意到问题不是来自上面的代码,而是来自测试部分。

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 版本是 ^5.0.5

2 个答案:

答案 0 :(得分:1)

更新:

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));
  }
}

答案 1 :(得分:0)

这个问题是由于 Mockito 版本造成的,我采用的是旧方法。

然后新的与 https://flutter.dev/docs/cookbook/testing/unit/mocking 完全一样,通过生成一个新的模拟文件,该文件创建一个模拟类,扩展模拟并使用 builder_runner 包实现 http.client。

<块引用>

使用 @GenerateMocks([http.Client]) 在main函数前的注解很重要