Unverified Commit 714dd2fe authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[null-safety] remove mockito from network tests (#64284)

More work towards removal of mockito to facilitate strong null safety tests.

#62886
parent dae720be
...@@ -13,8 +13,8 @@ import 'dart:ui' show Codec, FrameInfo; ...@@ -13,8 +13,8 @@ import 'dart:ui' show Codec, FrameInfo;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart'; import 'package:flutter/painting.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import '../flutter_test_alternative.dart' show Fake;
import '../rendering/rendering_tester.dart'; import '../rendering/rendering_tester.dart';
import 'image_data.dart'; import 'image_data.dart';
...@@ -25,10 +25,10 @@ void main() { ...@@ -25,10 +25,10 @@ void main() {
return PaintingBinding.instance.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling); return PaintingBinding.instance.instantiateImageCodec(bytes, cacheWidth: cacheWidth, cacheHeight: cacheHeight, allowUpscaling: allowUpscaling);
}; };
_MockHttpClient httpClient; _FakeHttpClient httpClient;
setUp(() { setUp(() {
httpClient = _MockHttpClient(); httpClient = _FakeHttpClient();
debugNetworkImageHttpClientProvider = () => httpClient; debugNetworkImageHttpClientProvider = () => httpClient;
}); });
...@@ -42,11 +42,7 @@ void main() { ...@@ -42,11 +42,7 @@ void main() {
final int errorStatusCode = HttpStatus.notFound; final int errorStatusCode = HttpStatus.notFound;
const String requestUrl = 'foo-url'; const String requestUrl = 'foo-url';
final _MockHttpClientRequest request = _MockHttpClientRequest(); httpClient.request.response.statusCode = errorStatusCode;
final _MockHttpClientResponse response = _MockHttpClientResponse();
when(httpClient.getUrl(any)).thenAnswer((_) => Future<HttpClientRequest>.value(request));
when(request.close()).thenAnswer((_) => Future<HttpClientResponse>.value(response));
when(response.statusCode).thenReturn(errorStatusCode);
final Completer<dynamic> caughtError = Completer<dynamic>(); final Completer<dynamic> caughtError = Completer<dynamic>();
...@@ -84,7 +80,7 @@ void main() { ...@@ -84,7 +80,7 @@ void main() {
}); });
test('Uses the HttpClient provided by debugNetworkImageHttpClientProvider if set', () async { test('Uses the HttpClient provided by debugNetworkImageHttpClientProvider if set', () async {
when(httpClient.getUrl(any)).thenThrow('client1'); httpClient.thrownError = 'client1';
final List<dynamic> capturedErrors = <dynamic>[]; final List<dynamic> capturedErrors = <dynamic>[];
Future<void> loadNetworkImage() async { Future<void> loadNetworkImage() async {
...@@ -101,15 +97,15 @@ void main() { ...@@ -101,15 +97,15 @@ void main() {
await loadNetworkImage(); await loadNetworkImage();
expect(capturedErrors, <dynamic>['client1']); expect(capturedErrors, <dynamic>['client1']);
final _MockHttpClient client2 = _MockHttpClient(); final _FakeHttpClient client2 = _FakeHttpClient();
when(client2.getUrl(any)).thenThrow('client2'); client2.thrownError = 'client2';
debugNetworkImageHttpClientProvider = () => client2; debugNetworkImageHttpClientProvider = () => client2;
await loadNetworkImage(); await loadNetworkImage();
expect(capturedErrors, <dynamic>['client1', 'client2']); expect(capturedErrors, <dynamic>['client1', 'client2']);
}, skip: isBrowser); // Browser implementation does not use HTTP client but an <img> tag. }, skip: isBrowser); // Browser implementation does not use HTTP client but an <img> tag.
test('Propagates http client errors during resolve()', () async { test('Propagates http client errors during resolve()', () async {
when(httpClient.getUrl(any)).thenThrow(Error()); httpClient.thrownError = Error();
bool uncaught = false; bool uncaught = false;
final FlutterExceptionHandler oldError = FlutterError.onError; final FlutterExceptionHandler oldError = FlutterError.onError;
...@@ -141,30 +137,11 @@ void main() { ...@@ -141,30 +137,11 @@ void main() {
Uint8List.fromList(kTransparentImage.skip(offset).take(chunkSize).toList()), Uint8List.fromList(kTransparentImage.skip(offset).take(chunkSize).toList()),
]; ];
final Completer<void> imageAvailable = Completer<void>(); final Completer<void> imageAvailable = Completer<void>();
final _MockHttpClientRequest request = _MockHttpClientRequest();
final _MockHttpClientResponse response = _MockHttpClientResponse(); httpClient.request.response
when(httpClient.getUrl(any)).thenAnswer((_) => Future<HttpClientRequest>.value(request)); ..statusCode = HttpStatus.ok
when(request.close()).thenAnswer((_) => Future<HttpClientResponse>.value(response)); ..contentLength = kTransparentImage.length
when(response.statusCode).thenReturn(HttpStatus.ok); ..content = chunks;
when(response.contentLength).thenReturn(kTransparentImage.length);
when(response.listen(
any,
onDone: anyNamed('onDone'),
onError: anyNamed('onError'),
cancelOnError: anyNamed('cancelOnError'),
)).thenAnswer((Invocation invocation) {
final void Function(List<int>) onData = invocation.positionalArguments[0] as void Function(List<int>);
final void Function(Object) onError = invocation.namedArguments[#onError] as void Function(Object);
final VoidCallback onDone = invocation.namedArguments[#onDone] as VoidCallback;
final bool cancelOnError = invocation.namedArguments[#cancelOnError] as bool;
return Stream<Uint8List>.fromIterable(chunks).listen(
onData,
onDone: onDone,
onError: onError,
cancelOnError: cancelOnError,
);
});
final ImageProvider imageProvider = NetworkImage(nonconst('foo')); final ImageProvider imageProvider = NetworkImage(nonconst('foo'));
final ImageStream result = imageProvider.resolve(ImageConfiguration.empty); final ImageStream result = imageProvider.resolve(ImageConfiguration.empty);
...@@ -189,11 +166,10 @@ void main() { ...@@ -189,11 +166,10 @@ void main() {
}, skip: isBrowser); // Browser loads images through <img> not Http. }, skip: isBrowser); // Browser loads images through <img> not Http.
test('NetworkImage is evicted from cache on SocketException', () async { test('NetworkImage is evicted from cache on SocketException', () async {
final _MockHttpClient mockHttpClient = _MockHttpClient(); final _FakeHttpClient mockHttpClient = _FakeHttpClient();
when(mockHttpClient.getUrl(any)).thenAnswer((_) => throw const SocketException('test exception')); mockHttpClient.thrownError = const SocketException('test exception');
debugNetworkImageHttpClientProvider = () => mockHttpClient; debugNetworkImageHttpClientProvider = () => mockHttpClient;
final ImageProvider imageProvider = NetworkImage(nonconst('testing.url')); final ImageProvider imageProvider = NetworkImage(nonconst('testing.url'));
expect(imageCache.pendingImageCount, 0); expect(imageCache.pendingImageCount, 0);
expect(imageCache.statusForKey(imageProvider).untracked, true); expect(imageCache.statusForKey(imageProvider).untracked, true);
...@@ -232,30 +208,10 @@ void main() { ...@@ -232,30 +208,10 @@ void main() {
for (int offset = 0; offset < kTransparentImage.length; offset += chunkSize) for (int offset = 0; offset < kTransparentImage.length; offset += chunkSize)
Uint8List.fromList(kTransparentImage.skip(offset).take(chunkSize).toList()), Uint8List.fromList(kTransparentImage.skip(offset).take(chunkSize).toList()),
]; ];
final _MockHttpClientRequest request = _MockHttpClientRequest(); httpClient.request.response
final _MockHttpClientResponse response = _MockHttpClientResponse(); ..statusCode = HttpStatus.ok
when(httpClient.getUrl(any)).thenAnswer((_) => Future<HttpClientRequest>.value(request)); ..contentLength = kTransparentImage.length
when(request.close()).thenAnswer((_) => Future<HttpClientResponse>.value(response)); ..content = chunks;
when(response.statusCode).thenReturn(HttpStatus.ok);
when(response.contentLength).thenReturn(kTransparentImage.length);
when(response.listen(
any,
onDone: anyNamed('onDone'),
onError: anyNamed('onError'),
cancelOnError: anyNamed('cancelOnError'),
)).thenAnswer((Invocation invocation) {
final void Function(List<int>) onData = invocation.positionalArguments[0] as void Function(List<int>);
final void Function(Object) onError = invocation.namedArguments[#onError] as void Function(Object);
final VoidCallback onDone = invocation.namedArguments[#onDone] as VoidCallback;
final bool cancelOnError = invocation.namedArguments[#cancelOnError] as bool;
return Stream<Uint8List>.fromIterable(chunks).listen(
onData,
onDone: onDone,
onError: onError,
cancelOnError: cancelOnError,
);
});
const NetworkImage provider = NetworkImage(url); const NetworkImage provider = NetworkImage(url);
...@@ -263,12 +219,51 @@ void main() { ...@@ -263,12 +219,51 @@ void main() {
expect(completer.debugLabel, url); expect(completer.debugLabel, url);
}); });
}
class _FakeHttpClient extends Fake implements HttpClient {
final _FakeHttpClientRequest request = _FakeHttpClientRequest();
dynamic thrownError;
@override
Future<HttpClientRequest> getUrl(Uri url) async {
if (thrownError != null) {
throw thrownError;
}
return request;
}
}
class _FakeHttpClientRequest extends Fake implements HttpClientRequest {
final _FakeHttpClientResponse response = _FakeHttpClientResponse();
@override
Future<HttpClientResponse> close() async {
return response;
}
} }
class _MockHttpClient extends Mock implements HttpClient {} class _FakeHttpClientResponse extends Fake implements HttpClientResponse {
class _MockHttpClientRequest extends Mock implements HttpClientRequest {} @override
class _MockHttpClientResponse extends Mock implements HttpClientResponse {} int statusCode = HttpStatus.ok;
@override
int contentLength = 0;
@override
HttpClientResponseCompressionState get compressionState => HttpClientResponseCompressionState.notCompressed;
List<List<int>> content;
@override
StreamSubscription<List<int>> listen(void Function(List<int> event) onData, {Function onError, void Function() onDone, bool cancelOnError}) {
return Stream<List<int>>.fromIterable(content).listen(
onData,
onDone: onDone,
onError: onError,
cancelOnError: cancelOnError,
);
}
}
class FakeCodec implements Codec { class FakeCodec implements Codec {
@override @override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment