Anthony Chang
Anthony Chang

Reputation: 43

How to mock HttpClientResponse to return a String

I am trying to write a test after refactoring to dart:io.HttpClient following https://flutter.io/networking/

Everything seems to work well up until

var responseBody = await response.transform(utf8.decoder).join();

The following test throws a NoSuchMethodError: The method 'join' was called on null.

MockHttpClient http = new MockHttpClient();
MockHttpClientRequest request = new MockHttpClientRequest();
MockHttpHeaders headers = new MockHttpHeaders();
MockHttpClientResponse response = new MockHttpClientResponse();
MockStream stream = new MockStream();
when(http.getUrl(Uri.parse('http://www.example.com/')))
    .thenReturn(new Future.value(request));
when(request.headers)
    .thenReturn(headers);
when(request.close())
    .thenReturn(new Future.value(response));
when(response.transform(utf8.decoder))
    .thenReturn(stream);
when(stream.join())
    .thenReturn(new Future.value('{"error": {"message": "Some error"}}'));

I did see How to mock server response - client on server side, but that uses the http package, not dart:io.

I also tried https://github.com/flutter/flutter/blob/master/dev/manual_tests/test/mock_image_http.dart but that also returns a null.

Much thanks in advance!

Upvotes: 4

Views: 1999

Answers (1)

Jonah Williams
Jonah Williams

Reputation: 21441

The problem is that when you mock stream you actually need to implement a ton of different methods to get it to work properly. It is better to use a real Stream if you can like in the example in the flutter repo. To make sure your body is correctly set, use the utf8 encoder.

final MockHttpClientResponse response = new MockHttpClientResponse();
// encode the response body as bytes.
final List<int> body = utf8.encode('{"foo":2}');

when(response.listen(typed(any))).thenAnswer((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>>[body]).listen(onData, onDone: onDone, onError: onError, cancelOnError: cancelOnError);
});

Upvotes: 4

Related Questions