Как использовать Mockito для тестирования отправки HTTP в Dart?

#dart #mockito

Вопрос:

Я пытаюсь использовать Mockito в dart для тестирования своих классов API.

Я создал a Request для того, чтобы задать такую информацию, как заголовки (агент пользователя и т.д.). Затем я использую макет, созданный с помощью @GenerateMocks([http.Client]) аннотации к send индивидуальному запросу.

Вот где для меня все усложняется. Get Post запросы или (с помощью методов client.get или client.post ) возвращают ответ, который достаточно легко проверить.

На самом деле, пример теста Mockito на веб-сайте состоит из нескольких строк:

 when(client
          .get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1')))
      .thenAnswer((_) async =>
          http.Response('{"userId": 1, "id": 2, "title": "mock"}', 200));

  expect(await fetchAlbum(client), isA<Album>());
 

Я не могу понять , как это сделать в ситуации а client.send , которая вместо этого возвращает StreamedResponse а.

Кусочки и фрагменты, которые я собрал до сих пор, не удалось собрать… Я даже не уверен, к чему стремиться.

   final client = MockClient();

  final http.Request request = RequestBuilder.build("testedRoute", 
    secure: false);
  final String expectedResponse = "some json we (might) get from the server";
  final List<int> expectedBody = utf8.encode(expectedResponse);

  final expectedAnswer = (Invocation invocation) {
  final void Function(List<int>) onData = invocation.positionalArguments[0];
  final void Function() onDone = invocation.namedArguments[#onDone];
  final void Function(Object, [StackTrace]) onError = invocation.namedArguments[#onError];
  final bool cancelOnError = invocation.namedArguments[#cancelOnError];
return new Stream<List<int>>.fromIterable(<List<int>>[expectedBody]).listen(onData, onDone: onDone, onError: onError, cancelOnError: cancelOnError);
  };
  // Use Mockito to return a successful response when it calls the
  // provided http.Client.
  // ***************
  // WHEN
  Future<http.StreamedResponse> streamedResponseFuture = when(
      client.send(request)
  )
 // ***************
 // THEN 
  .thenAnswer(
    // Future<StreamedResponse> Function(Invocation) answer
    (result) async { 
      // return http.StreamedResponse( expectedAnswer, 200);
      return http.StreamedResponse( Stream<List<int>>.fromIterable(<List<int>>[expectedBody]), 200);
    }
           );

final fetchResult = await APIManager().fetchThings();
expect(fetchResult, isNotEmpty);
expect(fetchResult.first, isA<Thing>());
 

Комментарии:

1. Если вы используете package:http , вместо того , чтобы создавать свой собственный Mock http.Client , вы должны использовать MockClient класс , который он вам предоставляет. Он предоставляет MockClient.streaming конструктор для StreamedResponse s.

2. @jamesdlin спасибо! Теперь у меня все галочки зеленые 🙂

Ответ №1:

Благодаря @Jamesdlin у меня это получилось! Я действительно сбился с курса здесь, и вот код, который я сейчас использую:

  test('returns an list of Things if the http call completes successfully', () async {
  var client = testing.MockClient.streaming((request, bodyStream) {
    return bodyStream.bytesToString().then((bodyString) {
      var controller = StreamController<List<int>>(sync: true);
      Future.sync(() {

        final String expectedResponse = "some json we (might) get from the server";
        final List<int> expectedBody = utf8.encode(expectedResponse);
        controller.add(expectedBody);
        controller.close();
      });
      return http.StreamedResponse(controller.stream, 200);
    });
    });
  // Run a send manually to demonstrate what the return is supposed to hold
  client.send(http.Request(HttpMethod.GET.toString(),Uri(path:"my path")))
    .then((value) =>
    value.stream.first.then((value) {
      final thing = utf8.decode(value).toString();
      debugPrint("******************** $thing *****************");
      return thing;
    })
  );
  final fetchThingsResult = await APIManager(client: client).fetchThings();
  expect(fetchThingsResult , isNotEmpty);
  expect(fetchThingsResult .first, isA<Thing>());
});