【问题标题】:Mocktail: type 'Null' is not a subtype of type 'Future<Response>'Mocktail:“Null”类型不是“Future<Response>”类型的子类型
【发布时间】:2021-11-09 04:39:59
【问题描述】:

我一直在尝试按照 Felangel 的 Weather tutorial 测试我的 API Provider,因为它与我的代码非常相似,但我无法让它工作。

api_provider_test.dart

import 'package:stock_mobile/data/models/user.dart';
import 'package:test/test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:http/http.dart' as http;
import 'package:stock_mobile/data/providers/api_provider.dart';

class MockHttpClient extends Mock implements http.Client {}

class MockResponse extends Mock implements http.Response {}

class FakeUri extends Fake implements Uri {}

void main() {
  group('ApiProvider', () {
    late http.Client httpClient;
    late ApiProvider apiProvider;

    setUpAll(() {
      registerFallbackValue(FakeUri());
    });

    setUp(() {
      httpClient = MockHttpClient();
      apiProvider = ApiProvider(httpClient: httpClient);
    });

    group('login', () {
      test('Throws ApiException non-200 response', () async {
        final response = MockResponse();

        when(() => response.statusCode).thenReturn(400);
        when(() => response.body).thenReturn('');
        when(() => httpClient.post(any())).thenAnswer((_) async => response);

        final actual = await apiProvider.login(const User.empty());

        expect(actual, throwsException);
      });
    });
  });
}

api_provider.dart

import 'dart:convert';

import 'package:http/http.dart' as http;
import 'package:stock_mobile/data/models/user.dart';

class ApiProvider {
  ApiProvider({http.Client? httpClient})
      : _httpClient = httpClient ?? http.Client();

  static const _baseUrl = '192.168.0.5:3000';
  final http.Client _httpClient;

  Future<String> login(User user) async {
    final loginRequest = Uri.http(_baseUrl, '/login');

    final loginResponse = await _httpClient.post(loginRequest, body: {
      "username": user.username,
      "password": user.password,
    });

    if (loginResponse.statusCode != 200) {
      throw Exception();
    }

    return jsonDecode(loginResponse.body);
  }
}

user.dart

import 'package:equatable/equatable.dart';

class User extends Equatable {
  const User(this.username, this.password);

  final String username;
  final String password;

  const User.empty({
    this.username = '',
    this.password = '',
  });

  @override
  String toString() {
    return 'User{username: $username, password: $password}';
  }

  @override
  List<Object?> get props => [username, password];
}

当我尝试运行代码时,我得到了这个错误:

package:http/src/client.dart 62:20                            MockHttpClient.post
package:stock_mobile/data/providers/api_provider.dart 17:45  ApiProvider.login
test\unit\api_provider_test.dart 42:42                             main.<fn>.<fn>.<fn>
test\unit\api_provider_test.dart 35:52                             main.<fn>.<fn>.<fn>

type 'Null' is not a subtype of type 'Future<Response>'

然后,我尝试通过在 api_provider_test.dart 的测试中添加 when(() =&gt; apiProvider.login(const User.empty())).thenAnswer((_) async =&gt; response.body); 来修复它,因为关于此错误的常见问题解答 here,但我无法使其正常工作。

这是错误:

package:http/src/client.dart 62:20                            MockHttpClient.post
package:stock_mobile/data/providers/api_provider.dart 17:45  ApiProvider.login
test\unit\api_provider_test.dart 34:32                             main.<fn>.<fn>.<fn>.<fn>
package:mocktail/src/mocktail.dart 211:8                      when.<fn>
test\unit\api_provider_test.dart 34:13                             main.<fn>.<fn>.<fn>
test\unit\api_provider_test.dart 28:52                             main.<fn>.<fn>.<fn>
===== asynchronous gap ===========================
dart:async                                                    _completeOnAsyncError
package:stock_mobile/data/providers/api_provider.dart        ApiProvider.login
test\unit\api_provider_test.dart 34:32                             main.<fn>.<fn>.<fn>.<fn>
package:mocktail/src/mocktail.dart 211:8                      when.<fn>
test\unit\api_provider_test.dart 34:13                             main.<fn>.<fn>.<fn>
test\unit\api_provider_test.dart 28:52                             main.<fn>.<fn>.<fn>
type 'Future<String>' is not a subtype of type 'Future<Response>'
package:http/src/client.dart 62:20                            MockHttpClient.post
package:stock_mobile/data/providers/api_provider.dart 17:45  ApiProvider.login
test\unit\api_provider_test.dart 36:42                             main.<fn>.<fn>.<fn>
test\unit\api_provider_test.dart 28:52                             main.<fn>.<fn>.<fn>

type 'Null' is not a subtype of type 'Future<Response>'

提前谢谢...

【问题讨论】:

    标签: flutter unit-testing dart


    【解决方案1】:

    我认为您在模拟 HttpClient 方法时缺少命名参数。

    替换 when(() =&gt; httpClient.post(any())).thenAnswer((_) async =&gt; response);

    when(() => httpClient.post(any(), body: any(named: "body")))
                .thenAnswer((_) async => response);
    

    这现在应该与您的方法调用正确匹配。

    【讨论】:

      猜你喜欢
      • 2021-08-26
      • 2020-10-13
      • 2022-06-23
      • 2020-11-19
      • 1970-01-01
      • 2020-09-24
      • 2020-09-11
      • 2021-10-20
      • 2023-03-30
      相关资源
      最近更新 更多