Allow new methods to be added to ui.Image for tests (#65876)

Remove fake image implementations, add createTestImage to flutter_test
diff --git a/dev/manual_tests/test/mock_image_http.dart b/dev/manual_tests/test/mock_image_http.dart
index d2f68d3..1a15b7a 100644
--- a/dev/manual_tests/test/mock_image_http.dart
+++ b/dev/manual_tests/test/mock_image_http.dart
@@ -6,7 +6,7 @@
 
 import 'package:mockito/mockito.dart';
 
-import '../../../packages/flutter/test/painting/image_data.dart';
+import '../../../packages/flutter/test/image_data.dart';
 
 // Returns a mock HTTP client that responds with an image to all requests.
 MockHttpClient createMockImageHttpClient(SecurityContext _) {
diff --git a/dev/tracing_tests/test/image_cache_tracing_test.dart b/dev/tracing_tests/test/image_cache_tracing_test.dart
index 3d8a9b3..bae94ab 100644
--- a/dev/tracing_tests/test/image_cache_tracing_test.dart
+++ b/dev/tracing_tests/test/image_cache_tracing_test.dart
@@ -5,8 +5,6 @@
 import 'dart:convert';
 import 'dart:developer' as developer;
 import 'dart:isolate' as isolate;
-import 'dart:typed_data';
-import 'dart:ui' as ui;
 
 import 'package:flutter/painting.dart';
 import 'package:flutter_test/flutter_test.dart';
@@ -40,8 +38,7 @@
     );
     PaintingBinding.instance.imageCache.clear();
 
-    // ignore: invalid_use_of_protected_member
-    completer2.setImage(const ImageInfo(image: TestImage()));
+    completer2.testSetImage(ImageInfo(image: await createTestImage()));
     PaintingBinding.instance.imageCache.putIfAbsent(
       'Test2',
       () => completer2,
@@ -76,7 +73,7 @@
         },
         <String, dynamic>{
           'name': 'ImageCache.evict',
-          'args': <String, dynamic>{'sizeInBytes': 0, 'isolateId': isolateId}
+          'args': <String, dynamic>{'sizeInBytes': 4, 'isolateId': isolateId}
         },
       ],
     );
@@ -110,20 +107,8 @@
   return true;
 }
 
-class TestImageStreamCompleter extends ImageStreamCompleter {}
-
-class TestImage implements ui.Image {
-  const TestImage({this.height = 0, this.width = 0});
-  @override
-  final int height;
-  @override
-  final int width;
-
-  @override
-  void dispose() { }
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) {
-    throw UnimplementedError();
+class TestImageStreamCompleter extends ImageStreamCompleter {
+  void testSetImage(ImageInfo image) {
+    setImage(image);
   }
 }
diff --git a/dev/tracing_tests/test/image_painting_event_test.dart b/dev/tracing_tests/test/image_painting_event_test.dart
index a786cce..c07321e 100644
--- a/dev/tracing_tests/test/image_painting_event_test.dart
+++ b/dev/tracing_tests/test/image_painting_event_test.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 import 'dart:convert' show jsonEncode;
 import 'dart:developer' as developer;
-import 'dart:typed_data';
 import 'dart:ui' as ui;
 
 import 'package:flutter/painting.dart';
@@ -46,7 +45,7 @@
     final Completer<Event> completer = Completer<Event>();
     vmService.onExtensionEvent.first.then(completer.complete);
 
-    const TestImage image = TestImage(width: 300, height: 300);
+    final ui.Image image = await createTestImage(width: 300, height: 300);
     final TestCanvas canvas = TestCanvas();
     paintImage(
       canvas: canvas,
@@ -79,7 +78,7 @@
     final Completer<Event> completer = Completer<Event>();
     vmService.onExtensionEvent.first.then(completer.complete);
 
-    const TestImage image = TestImage(width: 300, height: 300);
+    final ui.Image image = await createTestImage(width: 300, height: 300);
     final TestCanvas canvas = TestCanvas();
     paintImage(
       canvas: canvas,
@@ -105,23 +104,6 @@
   }, skip: isBrowser); // uses dart:isolate and io
 }
 
-class TestImage implements ui.Image {
-  const TestImage({this.height = 0, this.width = 0});
-  @override
-  final int height;
-  @override
-  final int width;
-
-  @override
-  void dispose() {}
-
-  @override
-  Future<ByteData> toByteData(
-      {ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba}) {
-    throw UnimplementedError();
-  }
-}
-
 class TestCanvas implements Canvas {
   @override
   void noSuchMethod(Invocation invocation) {}
diff --git a/packages/flutter/test/cupertino/bottom_tab_bar_test.dart b/packages/flutter/test/cupertino/bottom_tab_bar_test.dart
index 9747dc0..9f17634 100644
--- a/packages/flutter/test/cupertino/bottom_tab_bar_test.dart
+++ b/packages/flutter/test/cupertino/bottom_tab_bar_test.dart
@@ -10,7 +10,7 @@
 import 'package:flutter/rendering.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import '../painting/image_data.dart';
+import '../image_data.dart';
 import '../widgets/semantics_tester.dart';
 
 Future<void> pumpWidgetWithBoilerplate(WidgetTester tester, Widget widget) async {
@@ -257,7 +257,7 @@
   });
 
   testWidgets('Use active icon', (WidgetTester tester) async {
-    final MemoryImage activeIcon = MemoryImage(Uint8List.fromList(kBlueSquare));
+    final MemoryImage activeIcon = MemoryImage(Uint8List.fromList(kBlueSquarePng));
     final MemoryImage inactiveIcon = MemoryImage(Uint8List.fromList(kTransparentImage));
 
     await pumpWidgetWithBoilerplate(tester, MediaQuery(
diff --git a/packages/flutter/test/cupertino/material/tab_scaffold_test.dart b/packages/flutter/test/cupertino/material/tab_scaffold_test.dart
index 04122e4..827b979 100644
--- a/packages/flutter/test/cupertino/material/tab_scaffold_test.dart
+++ b/packages/flutter/test/cupertino/material/tab_scaffold_test.dart
@@ -10,7 +10,7 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import '../../painting/image_data.dart';
+import '../../image_data.dart';
 
 List<int> selectedTabs;
 
diff --git a/packages/flutter/test/cupertino/scaffold_test.dart b/packages/flutter/test/cupertino/scaffold_test.dart
index 6ab1b12..b100332 100644
--- a/packages/flutter/test/cupertino/scaffold_test.dart
+++ b/packages/flutter/test/cupertino/scaffold_test.dart
@@ -9,7 +9,7 @@
 import 'package:flutter/cupertino.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import '../painting/image_data.dart';
+import '../image_data.dart';
 import '../rendering/mock_canvas.dart';
 
 /// Integration tests testing both [CupertinoPageScaffold] and [CupertinoTabScaffold].
diff --git a/packages/flutter/test/cupertino/tab_scaffold_test.dart b/packages/flutter/test/cupertino/tab_scaffold_test.dart
index 65281a7..7e717be 100644
--- a/packages/flutter/test/cupertino/tab_scaffold_test.dart
+++ b/packages/flutter/test/cupertino/tab_scaffold_test.dart
@@ -9,7 +9,7 @@
 import 'package:flutter/cupertino.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import '../painting/image_data.dart';
+import '../image_data.dart';
 import '../rendering/rendering_tester.dart';
 
 List<int> selectedTabs;
diff --git a/packages/flutter/test/flutter_test_alternative.dart b/packages/flutter/test/flutter_test_alternative.dart
index 9110617..5eef49a 100644
--- a/packages/flutter/test/flutter_test_alternative.dart
+++ b/packages/flutter/test/flutter_test_alternative.dart
@@ -12,6 +12,7 @@
 
 export 'package:test_api/test_api.dart' hide TypeMatcher, isInstanceOf; // ignore: deprecated_member_use
 export 'package:test_api/fake.dart'; // ignore: deprecated_member_use
+export 'package:flutter_test/flutter_test.dart' show createTestImage;
 
 /// A matcher that compares the type of the actual value to the type argument T.
 test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
diff --git a/packages/flutter/test/painting/image_data.dart b/packages/flutter/test/image_data.dart
similarity index 98%
rename from packages/flutter/test/painting/image_data.dart
rename to packages/flutter/test/image_data.dart
index 3735943..4af2249 100644
--- a/packages/flutter/test/painting/image_data.dart
+++ b/packages/flutter/test/image_data.dart
@@ -4,9 +4,8 @@
 
 // @dart = 2.8
 
-
 /// A 50x50 blue square png.
-const List<int> kBlueSquare = <int>[
+const List<int> kBlueSquarePng = <int>[
   0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49,
   0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32, 0x08, 0x06,
   0x00, 0x00, 0x00, 0x1e, 0x3f, 0x88, 0xb1, 0x00, 0x00, 0x00, 0x48, 0x49, 0x44,
@@ -41,7 +40,7 @@
   0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b,
 ];
 
-// A PNG with 100x100 blue pixels.
+/// A PNG with 100x100 blue pixels.
 //
 // Constructed by the following code:
 // ```dart
diff --git a/packages/flutter/test/material/circle_avatar_test.dart b/packages/flutter/test/material/circle_avatar_test.dart
index aec85d2..13830c9 100644
--- a/packages/flutter/test/material/circle_avatar_test.dart
+++ b/packages/flutter/test/material/circle_avatar_test.dart
@@ -10,7 +10,7 @@
 import 'package:flutter/rendering.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import '../painting/image_data.dart';
+import '../image_data.dart';
 
 void main() {
   testWidgets('CircleAvatar with dark background color', (WidgetTester tester) async {
diff --git a/packages/flutter/test/painting/binding_test.dart b/packages/flutter/test/painting/binding_test.dart
index bf9da5b..bea214f 100644
--- a/packages/flutter/test/painting/binding_test.dart
+++ b/packages/flutter/test/painting/binding_test.dart
@@ -9,16 +9,18 @@
 import 'package:flutter/foundation.dart';
 import 'package:flutter/scheduler.dart';
 import 'package:flutter/services.dart';
-import 'package:flutter_test/flutter_test.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter/painting.dart';
 
+import 'package:flutter_test/flutter_test.dart';
 
-void main() {
+Future<void> main() async {
+  final ui.Image image = await createTestImage();
+
   testWidgets('didHaveMemoryPressure clears imageCache', (WidgetTester tester) async {
     imageCache.putIfAbsent(1, () => OneFrameImageStreamCompleter(
       Future<ImageInfo>.value(ImageInfo(
-        image: FakeImage(),
+        image: image,
         scale: 1.0,
       ),
     )));
@@ -115,19 +117,3 @@
     super.clearLiveImages();
   }
 }
-
-class FakeImage implements ui.Image {
-  @override
-  void dispose() {}
-
-  @override
-  int get height => 10;
-
-  @override
-  Future<ByteData> toByteData({ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba}) {
-    throw UnimplementedError();
-  }
-
-  @override
-  int get width => 10;
-}
diff --git a/packages/flutter/test/painting/decoration_test.dart b/packages/flutter/test/painting/decoration_test.dart
index b309362..a4161f0 100644
--- a/packages/flutter/test/painting/decoration_test.dart
+++ b/packages/flutter/test/painting/decoration_test.dart
@@ -6,8 +6,7 @@
 
 @TestOn('!chrome')
 import 'dart:async';
-import 'dart:typed_data';
-import 'dart:ui' as ui show Image, ImageByteFormat, ColorFilter;
+import 'dart:ui' as ui show Image, ColorFilter;
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/painting.dart';
@@ -29,6 +28,10 @@
 }
 
 class SynchronousTestImageProvider extends ImageProvider<int> {
+  const SynchronousTestImageProvider(this.image);
+
+  final ui.Image image;
+
   @override
   Future<int> obtainKey(ImageConfiguration configuration) {
     return SynchronousFuture<int>(1);
@@ -37,7 +40,7 @@
   @override
   ImageStreamCompleter load(int key, DecoderCallback decode) {
     return OneFrameImageStreamCompleter(
-      SynchronousFuture<ImageInfo>(TestImageInfo(key, image: TestImage(), scale: 1.0))
+      SynchronousFuture<ImageInfo>(TestImageInfo(key, image: image, scale: 1.0))
     );
   }
 }
@@ -73,6 +76,10 @@
 }
 
 class DelayedImageProvider extends ImageProvider<DelayedImageProvider> {
+  DelayedImageProvider(this.image);
+
+  final ui.Image image;
+
   final Completer<ImageInfo> _completer = Completer<ImageInfo>();
 
   @override
@@ -85,30 +92,14 @@
     return OneFrameImageStreamCompleter(_completer.future);
   }
 
-  void complete() {
-    _completer.complete(ImageInfo(image: TestImage()));
+  Future<void> complete() async {
+    _completer.complete(ImageInfo(image: image));
   }
 
   @override
   String toString() => '${describeIdentity(this)}()';
 }
 
-class TestImage implements ui.Image {
-  @override
-  int get width => 100;
-
-  @override
-  int get height => 100;
-
-  @override
-  void dispose() { }
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) async {
-    throw UnsupportedError('Cannot encode test image');
-  }
-}
-
 void main() {
   TestRenderingFlutterBinding(); // initializes the imageCache
 
@@ -141,8 +132,9 @@
     expect(a, equals(b));
   });
 
-  test('BoxDecorationImageListenerSync', () {
-    final ImageProvider imageProvider = SynchronousTestImageProvider();
+  test('BoxDecorationImageListenerSync', () async {
+    final ui.Image image = await createTestImage(width: 100, height: 100);
+    final ImageProvider imageProvider = SynchronousTestImageProvider(image);
     final DecorationImage backgroundImage = DecorationImage(image: imageProvider);
 
     final BoxDecoration boxDecoration = BoxDecoration(image: backgroundImage);
@@ -183,11 +175,12 @@
 
   // Regression test for https://github.com/flutter/flutter/issues/7289.
   // A reference test would be better.
-  test('BoxDecoration backgroundImage clip', () {
+  test('BoxDecoration backgroundImage clip', () async {
+    final ui.Image image = await createTestImage(width: 100, height: 100);
     void testDecoration({ BoxShape shape = BoxShape.rectangle, BorderRadius borderRadius, bool expectClip }) {
       assert(shape != null);
-      FakeAsync().run((FakeAsync async) {
-        final DelayedImageProvider imageProvider = DelayedImageProvider();
+      FakeAsync().run((FakeAsync async) async {
+        final DelayedImageProvider imageProvider = DelayedImageProvider(image);
         final DecorationImage backgroundImage = DecorationImage(image: imageProvider);
 
         final BoxDecoration boxDecoration = BoxDecoration(
@@ -209,7 +202,7 @@
         // _BoxDecorationPainter._paintDecorationImage() resolves the background
         // image and adds a listener to the resolved image stream.
         boxPainter.paint(canvas, Offset.zero, imageConfiguration);
-        imageProvider.complete();
+        await imageProvider.complete();
 
         // Run the listener which calls onChanged() which saves an internal
         // reference to the TestImage.
@@ -237,10 +230,11 @@
     testDecoration(expectClip: false);
   });
 
-  test('DecorationImage test', () {
+  test('DecorationImage test', () async {
     const ColorFilter colorFilter = ui.ColorFilter.mode(Color(0xFF00FF00), BlendMode.src);
+    final ui.Image image = await createTestImage(width: 100, height: 100);
     final DecorationImage backgroundImage = DecorationImage(
-      image: SynchronousTestImageProvider(),
+      image: SynchronousTestImageProvider(image),
       colorFilter: colorFilter,
       fit: BoxFit.contain,
       alignment: Alignment.bottomLeft,
@@ -256,7 +250,7 @@
     final Invocation call = canvas.invocations.singleWhere((Invocation call) => call.memberName == #drawImageNine);
     expect(call.isMethod, isTrue);
     expect(call.positionalArguments, hasLength(4));
-    expect(call.positionalArguments[0], isA<TestImage>());
+    expect(call.positionalArguments[0], isA<ui.Image>());
     expect(call.positionalArguments[1], const Rect.fromLTRB(10.0, 20.0, 40.0, 60.0));
     expect(call.positionalArguments[2], const Rect.fromLTRB(0.0, 0.0, 100.0, 100.0));
     expect(call.positionalArguments[3], isA<Paint>());
@@ -265,10 +259,10 @@
     expect(call.positionalArguments[3].filterQuality, FilterQuality.low);
   });
 
-  test(
-      'DecorationImage with null textDirection configuration should throw Error', () {
+  test('DecorationImage with null textDirection configuration should throw Error', () async {
+    final ui.Image image = await createTestImage(width: 100, height: 100);
     final DecorationImage backgroundImage = DecorationImage(
-      image: SynchronousTestImageProvider(),
+      image: SynchronousTestImageProvider(image),
       matchTextDirection: true,
     );
     final BoxDecoration boxDecoration = BoxDecoration(
@@ -434,12 +428,12 @@
     expect(Decoration.lerp(const FlutterLogoDecoration(), const BoxDecoration(), 1.0), isA<BoxDecoration>());
   });
 
-  test('paintImage BoxFit.none scale test', () {
+  test('paintImage BoxFit.none scale test', () async {
     for (double scale = 1.0; scale <= 4.0; scale += 1.0) {
       final TestCanvas canvas = TestCanvas(<Invocation>[]);
 
       const Rect outputRect = Rect.fromLTWH(30.0, 30.0, 250.0, 250.0);
-      final ui.Image image = TestImage();
+      final ui.Image image = await createTestImage(width: 100, height: 100);
 
       paintImage(
         canvas: canvas,
@@ -459,7 +453,7 @@
       expect(call.isMethod, isTrue);
       expect(call.positionalArguments, hasLength(4));
 
-      expect(call.positionalArguments[0], isA<TestImage>());
+      expect(call.positionalArguments[0], isA<ui.Image>());
 
       // sourceRect should contain all pixels of the source image
       expect(call.positionalArguments[1], Offset.zero & imageSize);
@@ -477,13 +471,13 @@
     }
   });
 
-  test('paintImage BoxFit.scaleDown scale test', () {
+  test('paintImage BoxFit.scaleDown scale test', () async {
     for (double scale = 1.0; scale <= 4.0; scale += 1.0) {
       final TestCanvas canvas = TestCanvas(<Invocation>[]);
 
       // container size > scaled image size
       const Rect outputRect = Rect.fromLTWH(30.0, 30.0, 250.0, 250.0);
-      final ui.Image image = TestImage();
+      final ui.Image image = await createTestImage(width: 100, height: 100);
 
       paintImage(
         canvas: canvas,
@@ -503,7 +497,7 @@
       expect(call.isMethod, isTrue);
       expect(call.positionalArguments, hasLength(4));
 
-      expect(call.positionalArguments[0], isA<TestImage>());
+      expect(call.positionalArguments[0], isA<ui.Image>());
 
       // sourceRect should contain all pixels of the source image
       expect(call.positionalArguments[1], Offset.zero & imageSize);
@@ -521,12 +515,12 @@
     }
   });
 
-  test('paintImage BoxFit.scaleDown test', () {
+  test('paintImage BoxFit.scaleDown test', () async {
     final TestCanvas canvas = TestCanvas(<Invocation>[]);
 
     // container height (20 px) < scaled image height (50 px)
     const Rect outputRect = Rect.fromLTWH(30.0, 30.0, 250.0, 20.0);
-    final ui.Image image = TestImage();
+    final ui.Image image = await createTestImage(width: 100, height: 100);
 
     paintImage(
       canvas: canvas,
@@ -546,7 +540,7 @@
     expect(call.isMethod, isTrue);
     expect(call.positionalArguments, hasLength(4));
 
-    expect(call.positionalArguments[0], isA<TestImage>());
+    expect(call.positionalArguments[0], isA<ui.Image>());
 
     // sourceRect should contain all pixels of the source image
     expect(call.positionalArguments[1], Offset.zero & imageSize);
@@ -563,7 +557,7 @@
     expect(call.positionalArguments[3], isA<Paint>());
   });
 
-  test('paintImage boxFit, scale and alignment test', () {
+  test('paintImage boxFit, scale and alignment test', () async {
     const List<BoxFit> boxFits = <BoxFit>[
       BoxFit.contain,
       BoxFit.cover,
@@ -578,7 +572,7 @@
       final TestCanvas canvas = TestCanvas(<Invocation>[]);
 
       const Rect outputRect = Rect.fromLTWH(30.0, 30.0, 250.0, 250.0);
-      final ui.Image image = TestImage();
+      final ui.Image image = await createTestImage(width: 100, height: 100);
 
       paintImage(
         canvas: canvas,
@@ -601,9 +595,10 @@
     }
   });
 
-  test('scale cannot be null in DecorationImage', () {
+  test('scale cannot be null in DecorationImage', () async {
+    final ui.Image image = await createTestImage(width: 100, height: 100);
     try {
-      DecorationImage(scale: null, image: SynchronousTestImageProvider());
+      DecorationImage(scale: null, image: SynchronousTestImageProvider(image));
     } on AssertionError catch (error) {
       expect(error.toString(), contains('scale != null'));
       expect(error.toString(), contains('is not true'));
@@ -612,9 +607,10 @@
     fail('DecorationImage did not throw AssertionError when scale was null');
   });
 
-  test('DecorationImage scale test', () {
+  test('DecorationImage scale test', () async {
+    final ui.Image image = await createTestImage(width: 100, height: 100);
     final DecorationImage backgroundImage = DecorationImage(
-      image: SynchronousTestImageProvider(),
+      image: SynchronousTestImageProvider(image),
       scale: 4,
       alignment: Alignment.topLeft
     );
diff --git a/packages/flutter/test/painting/image_cache_clearing_test.dart b/packages/flutter/test/painting/image_cache_clearing_test.dart
index 6d0c542..94acdf3 100644
--- a/packages/flutter/test/painting/image_cache_clearing_test.dart
+++ b/packages/flutter/test/painting/image_cache_clearing_test.dart
@@ -10,8 +10,8 @@
 import 'package:flutter/painting.dart';
 import 'package:flutter_test/flutter_test.dart';
 
+import '../image_data.dart';
 import '../rendering/rendering_tester.dart';
-import 'image_data.dart';
 
 void main() {
   TestRenderingFlutterBinding();
diff --git a/packages/flutter/test/painting/image_cache_resize_test.dart b/packages/flutter/test/painting/image_cache_resize_test.dart
index 9c647d3..81b60dd 100644
--- a/packages/flutter/test/painting/image_cache_resize_test.dart
+++ b/packages/flutter/test/painting/image_cache_resize_test.dart
@@ -4,6 +4,8 @@
 
 // @dart = 2.8
 
+import 'dart:ui' as ui;
+
 import 'package:flutter/painting.dart';
 import '../flutter_test_alternative.dart';
 
@@ -22,10 +24,10 @@
   test('Image cache resizing based on count', () async {
     imageCache.maximumSize = 2;
 
-    final TestImageInfo a = await extractOneFrame(const TestImageProvider(1, 1).resolve(ImageConfiguration.empty)) as TestImageInfo;
-    final TestImageInfo b = await extractOneFrame(const TestImageProvider(2, 2).resolve(ImageConfiguration.empty)) as TestImageInfo;
-    final TestImageInfo c = await extractOneFrame(const TestImageProvider(3, 3).resolve(ImageConfiguration.empty)) as TestImageInfo;
-    final TestImageInfo d = await extractOneFrame(const TestImageProvider(1, 4).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo a = await extractOneFrame(TestImageProvider(1, 1, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo b = await extractOneFrame(TestImageProvider(2, 2, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo c = await extractOneFrame(TestImageProvider(3, 3, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo d = await extractOneFrame(TestImageProvider(1, 4, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(a.value, equals(1));
     expect(b.value, equals(2));
     expect(c.value, equals(3));
@@ -33,29 +35,29 @@
 
     imageCache.maximumSize = 0;
 
-    final TestImageInfo e = await extractOneFrame(const TestImageProvider(1, 5).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo e = await extractOneFrame(TestImageProvider(1, 5, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(e.value, equals(5));
 
-    final TestImageInfo f = await extractOneFrame(const TestImageProvider(1, 6).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo f = await extractOneFrame(TestImageProvider(1, 6, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(f.value, equals(6));
 
     imageCache.maximumSize = 3;
 
-    final TestImageInfo g = await extractOneFrame(const TestImageProvider(1, 7).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo g = await extractOneFrame(TestImageProvider(1, 7, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(g.value, equals(7));
 
-    final TestImageInfo h = await extractOneFrame(const TestImageProvider(1, 8).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo h = await extractOneFrame(TestImageProvider(1, 8, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(h.value, equals(7));
   });
 
   test('Image cache resizing based on size', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8); // 256 B.
+    final ui.Image testImage = await createTestImage(width: 8, height: 8); // 256 B.
     imageCache.maximumSizeBytes = 256 * 2;
 
-    final TestImageInfo a = await extractOneFrame(const TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
-    final TestImageInfo b = await extractOneFrame(const TestImageProvider(2, 2, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
-    final TestImageInfo c = await extractOneFrame(const TestImageProvider(3, 3, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
-    final TestImageInfo d = await extractOneFrame(const TestImageProvider(1, 4, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo a = await extractOneFrame(TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo b = await extractOneFrame(TestImageProvider(2, 2, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo c = await extractOneFrame(TestImageProvider(3, 3, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo d = await extractOneFrame(TestImageProvider(1, 4, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(a.value, equals(1));
     expect(b.value, equals(2));
     expect(c.value, equals(3));
@@ -63,18 +65,18 @@
 
     imageCache.maximumSizeBytes = 0;
 
-    final TestImageInfo e = await extractOneFrame(const TestImageProvider(1, 5, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo e = await extractOneFrame(TestImageProvider(1, 5, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(e.value, equals(5));
 
-    final TestImageInfo f = await extractOneFrame(const TestImageProvider(1, 6, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo f = await extractOneFrame(TestImageProvider(1, 6, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(f.value, equals(6));
 
     imageCache.maximumSizeBytes = 256 * 3;
 
-    final TestImageInfo g = await extractOneFrame(const TestImageProvider(1, 7, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo g = await extractOneFrame(TestImageProvider(1, 7, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(g.value, equals(7));
 
-    final TestImageInfo h = await extractOneFrame(const TestImageProvider(1, 8, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo h = await extractOneFrame(TestImageProvider(1, 8, image: testImage).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(h.value, equals(7));
   });
 }
diff --git a/packages/flutter/test/painting/image_cache_test.dart b/packages/flutter/test/painting/image_cache_test.dart
index fe8ef5a..d5af602 100644
--- a/packages/flutter/test/painting/image_cache_test.dart
+++ b/packages/flutter/test/painting/image_cache_test.dart
@@ -4,6 +4,8 @@
 
 // @dart = 2.8
 
+import 'dart:ui' as ui;
+
 import 'package:flutter/painting.dart';
 import '../flutter_test_alternative.dart';
 
@@ -23,82 +25,82 @@
   test('maintains cache size', () async {
     imageCache.maximumSize = 3;
 
-    final TestImageInfo a = await extractOneFrame(const TestImageProvider(1, 1).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo a = await extractOneFrame(TestImageProvider(1, 1, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(a.value, equals(1));
-    final TestImageInfo b = await extractOneFrame(const TestImageProvider(1, 2).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo b = await extractOneFrame(TestImageProvider(1, 2, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(b.value, equals(1));
-    final TestImageInfo c = await extractOneFrame(const TestImageProvider(1, 3).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo c = await extractOneFrame(TestImageProvider(1, 3, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(c.value, equals(1));
-    final TestImageInfo d = await extractOneFrame(const TestImageProvider(1, 4).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo d = await extractOneFrame(TestImageProvider(1, 4, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(d.value, equals(1));
-    final TestImageInfo e = await extractOneFrame(const TestImageProvider(1, 5).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo e = await extractOneFrame(TestImageProvider(1, 5, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(e.value, equals(1));
-    final TestImageInfo f = await extractOneFrame(const TestImageProvider(1, 6).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo f = await extractOneFrame(TestImageProvider(1, 6, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(f.value, equals(1));
 
     expect(f, equals(a));
 
     // cache still only has one entry in it: 1(1)
 
-    final TestImageInfo g = await extractOneFrame(const TestImageProvider(2, 7).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo g = await extractOneFrame(TestImageProvider(2, 7, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(g.value, equals(7));
 
     // cache has two entries in it: 1(1), 2(7)
 
-    final TestImageInfo h = await extractOneFrame(const TestImageProvider(1, 8).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo h = await extractOneFrame(TestImageProvider(1, 8, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(h.value, equals(1));
 
     // cache still has two entries in it: 2(7), 1(1)
 
-    final TestImageInfo i = await extractOneFrame(const TestImageProvider(3, 9).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo i = await extractOneFrame(TestImageProvider(3, 9, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(i.value, equals(9));
 
     // cache has three entries in it: 2(7), 1(1), 3(9)
 
-    final TestImageInfo j = await extractOneFrame(const TestImageProvider(1, 10).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo j = await extractOneFrame(TestImageProvider(1, 10, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(j.value, equals(1));
 
     // cache still has three entries in it: 2(7), 3(9), 1(1)
 
-    final TestImageInfo k = await extractOneFrame(const TestImageProvider(4, 11).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo k = await extractOneFrame(TestImageProvider(4, 11, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(k.value, equals(11));
 
     // cache has three entries: 3(9), 1(1), 4(11)
 
-    final TestImageInfo l = await extractOneFrame(const TestImageProvider(1, 12).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo l = await extractOneFrame(TestImageProvider(1, 12, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(l.value, equals(1));
 
     // cache has three entries: 3(9), 4(11), 1(1)
 
-    final TestImageInfo m = await extractOneFrame(const TestImageProvider(2, 13).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo m = await extractOneFrame(TestImageProvider(2, 13, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(m.value, equals(13));
 
     // cache has three entries: 4(11), 1(1), 2(13)
 
-    final TestImageInfo n = await extractOneFrame(const TestImageProvider(3, 14).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo n = await extractOneFrame(TestImageProvider(3, 14, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(n.value, equals(14));
 
     // cache has three entries: 1(1), 2(13), 3(14)
 
-    final TestImageInfo o = await extractOneFrame(const TestImageProvider(4, 15).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo o = await extractOneFrame(TestImageProvider(4, 15, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(o.value, equals(15));
 
     // cache has three entries: 2(13), 3(14), 4(15)
 
-    final TestImageInfo p = await extractOneFrame(const TestImageProvider(1, 16).resolve(ImageConfiguration.empty)) as TestImageInfo;
+    final TestImageInfo p = await extractOneFrame(TestImageProvider(1, 16, image: await createTestImage()).resolve(ImageConfiguration.empty)) as TestImageInfo;
     expect(p.value, equals(16));
 
     // cache has three entries: 3(14), 4(15), 1(16)
   });
 
   test('clear removes all images and resets cache size', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     expect(imageCache.currentSize, 0);
     expect(imageCache.currentSizeBytes, 0);
 
-    await extractOneFrame(const TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty));
-    await extractOneFrame(const TestImageProvider(2, 2, image: testImage).resolve(ImageConfiguration.empty));
+    await extractOneFrame(TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty));
+    await extractOneFrame(TestImageProvider(2, 2, image: testImage).resolve(ImageConfiguration.empty));
 
     expect(imageCache.currentSize, 2);
     expect(imageCache.currentSizeBytes, 256 * 2);
@@ -110,9 +112,9 @@
   });
 
   test('evicts individual images', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
-    await extractOneFrame(const TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty));
-    await extractOneFrame(const TestImageProvider(2, 2, image: testImage).resolve(ImageConfiguration.empty));
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
+    await extractOneFrame(TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty));
+    await extractOneFrame(TestImageProvider(2, 2, image: testImage).resolve(ImageConfiguration.empty));
 
     expect(imageCache.currentSize, 2);
     expect(imageCache.currentSizeBytes, 256 * 2);
@@ -122,10 +124,10 @@
   });
 
   test('Do not cache large images', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     imageCache.maximumSizeBytes = 1;
-    await extractOneFrame(const TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty));
+    await extractOneFrame(TestImageProvider(1, 1, image: testImage).resolve(ImageConfiguration.empty));
     expect(imageCache.currentSize, 0);
     expect(imageCache.currentSizeBytes, 0);
     expect(imageCache.maximumSizeBytes, 1);
@@ -143,7 +145,7 @@
   });
 
   test('already pending image is returned when it is put into the cache again', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
     final TestImageStreamCompleter completer2 = TestImageStreamCompleter();
@@ -160,7 +162,7 @@
   });
 
   test('pending image is removed when cache is cleared', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
     final TestImageStreamCompleter completer2 = TestImageStreamCompleter();
@@ -187,7 +189,7 @@
   });
 
   test('pending image is removed when image is evicted', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
     final TestImageStreamCompleter completer2 = TestImageStreamCompleter();
@@ -207,21 +209,25 @@
   });
 
   test("failed image can successfully be removed from the cache's pending images", () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
-    const FailingTestImageProvider(1, 1, image: testImage)
+    FailingTestImageProvider(1, 1, image: testImage)
         .resolve(ImageConfiguration.empty)
         .addListener(ImageStreamListener(
-          (ImageInfo image, bool synchronousCall) { },
+          (ImageInfo image, bool synchronousCall) {
+            fail('Image should not complete successfully');
+           },
           onError: (dynamic exception, StackTrace stackTrace) {
             final bool evictionResult = imageCache.evict(1);
             expect(evictionResult, isTrue);
           },
         ));
+    // yield an event turn so that async work can complete.
+    await null;
   });
 
   test('containsKey - pending', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
 
@@ -234,7 +240,7 @@
   });
 
   test('containsKey - completed', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
 
@@ -251,8 +257,8 @@
 
   test('putIfAbsent updates LRU properties of a live image', () async {
     imageCache.maximumSize = 1;
-    const TestImage testImage = TestImage(width: 8, height: 8);
-    const TestImage testImage2 = TestImage(width: 10, height: 10);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
+    final ui.Image testImage2 = await createTestImage(width: 10, height: 10);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter()..testSetImage(testImage);
     final TestImageStreamCompleter completer2 = TestImageStreamCompleter()..testSetImage(testImage2);
@@ -286,12 +292,12 @@
   test('Live image cache avoids leaks of unlistened streams', () async {
     imageCache.maximumSize = 3;
 
-    const TestImageProvider(1, 1).resolve(ImageConfiguration.empty);
-    const TestImageProvider(2, 2).resolve(ImageConfiguration.empty);
-    const TestImageProvider(3, 3).resolve(ImageConfiguration.empty);
-    const TestImageProvider(4, 4).resolve(ImageConfiguration.empty);
-    const TestImageProvider(5, 5).resolve(ImageConfiguration.empty);
-    const TestImageProvider(6, 6).resolve(ImageConfiguration.empty);
+    TestImageProvider(1, 1, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(2, 2, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(3, 3, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(4, 4, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(5, 5, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(6, 6, image: await createTestImage()).resolve(ImageConfiguration.empty);
 
     // wait an event loop to let image resolution process.
     await null;
@@ -303,12 +309,12 @@
   test('Disabled image cache does not leak live images', () async {
     imageCache.maximumSize = 0;
 
-    const TestImageProvider(1, 1).resolve(ImageConfiguration.empty);
-    const TestImageProvider(2, 2).resolve(ImageConfiguration.empty);
-    const TestImageProvider(3, 3).resolve(ImageConfiguration.empty);
-    const TestImageProvider(4, 4).resolve(ImageConfiguration.empty);
-    const TestImageProvider(5, 5).resolve(ImageConfiguration.empty);
-    const TestImageProvider(6, 6).resolve(ImageConfiguration.empty);
+    TestImageProvider(1, 1, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(2, 2, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(3, 3, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(4, 4, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(5, 5, image: await createTestImage()).resolve(ImageConfiguration.empty);
+    TestImageProvider(6, 6, image: await createTestImage()).resolve(ImageConfiguration.empty);
 
     // wait an event loop to let image resolution process.
     await null;
@@ -318,7 +324,7 @@
   });
 
   test('Evicting a pending image clears the live image by default', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
 
@@ -332,7 +338,7 @@
   });
 
   test('Evicting a pending image does clear the live image when includeLive is false and only cache listening', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
 
@@ -348,7 +354,7 @@
   });
 
   test('Evicting a pending image does clear the live image when includeLive is false and some other listener', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter();
 
@@ -365,7 +371,7 @@
   });
 
   test('Evicting a completed image does clear the live image by default', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter()
       ..testSetImage(testImage)
@@ -381,7 +387,7 @@
   });
 
   test('Evicting a completed image does not clear the live image when includeLive is set to false', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final TestImageStreamCompleter completer1 = TestImageStreamCompleter()
       ..testSetImage(testImage)
@@ -399,7 +405,7 @@
   });
 
   test('Clearing liveImages removes callbacks', () async {
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
 
     final ImageStreamListener listener = ImageStreamListener((ImageInfo info, bool syncCall) {});
 
@@ -442,7 +448,7 @@
     // If the live image did not track the size properly, the last line of
     // this test will fail.
 
-    const TestImage testImage = TestImage(width: 8, height: 8);
+    final ui.Image testImage = await createTestImage(width: 8, height: 8);
     const int testImageSize = 8 * 8 * 4;
 
     final ImageStreamListener listener = ImageStreamListener((ImageInfo info, bool syncCall) {});
diff --git a/packages/flutter/test/painting/image_decoder_test.dart b/packages/flutter/test/painting/image_decoder_test.dart
index 36ce220..aea7103 100644
--- a/packages/flutter/test/painting/image_decoder_test.dart
+++ b/packages/flutter/test/painting/image_decoder_test.dart
@@ -10,7 +10,7 @@
 import 'package:flutter/painting.dart';
 
 import '../flutter_test_alternative.dart';
-import 'image_data.dart';
+import '../image_data.dart';
 import 'painting_utils.dart';
 
 void main() {
diff --git a/packages/flutter/test/painting/image_provider_and_image_cache_test.dart b/packages/flutter/test/painting/image_provider_and_image_cache_test.dart
index 6195f99..7e9a3e1 100644
--- a/packages/flutter/test/painting/image_provider_and_image_cache_test.dart
+++ b/packages/flutter/test/painting/image_provider_and_image_cache_test.dart
@@ -12,8 +12,8 @@
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 
+import '../image_data.dart';
 import '../rendering/rendering_tester.dart';
-import 'image_data.dart';
 import 'mocks_for_image_cache.dart';
 
 void main() {
diff --git a/packages/flutter/test/painting/image_provider_network_image_test.dart b/packages/flutter/test/painting/image_provider_network_image_test.dart
index 7b02899..ee9fb00 100644
--- a/packages/flutter/test/painting/image_provider_network_image_test.dart
+++ b/packages/flutter/test/painting/image_provider_network_image_test.dart
@@ -15,8 +15,8 @@
 import 'package:flutter_test/flutter_test.dart';
 
 import '../flutter_test_alternative.dart' show Fake;
+import '../image_data.dart';
 import '../rendering/rendering_tester.dart';
-import 'image_data.dart';
 
 void main() {
   TestRenderingFlutterBinding();
diff --git a/packages/flutter/test/painting/image_provider_resize_image_test.dart b/packages/flutter/test/painting/image_provider_resize_image_test.dart
index 29afff6..21948fb 100644
--- a/packages/flutter/test/painting/image_provider_resize_image_test.dart
+++ b/packages/flutter/test/painting/image_provider_resize_image_test.dart
@@ -10,8 +10,8 @@
 import 'package:flutter/painting.dart';
 import 'package:flutter_test/flutter_test.dart';
 
+import '../image_data.dart';
 import '../rendering/rendering_tester.dart';
-import 'image_data.dart';
 
 void main() {
   TestRenderingFlutterBinding();
@@ -36,7 +36,7 @@
 
 
   test('ResizeImage resizes to the correct dimensions (down)', () async {
-    final Uint8List bytes = Uint8List.fromList(kBlueSquare);
+    final Uint8List bytes = Uint8List.fromList(kBlueSquarePng);
     final MemoryImage imageProvider = MemoryImage(bytes);
     final Size rawImageSize = await _resolveAndGetSize(imageProvider);
     expect(rawImageSize, const Size(50, 50));
diff --git a/packages/flutter/test/painting/image_provider_test.dart b/packages/flutter/test/painting/image_provider_test.dart
index ec81db8..3b2895f 100644
--- a/packages/flutter/test/painting/image_provider_test.dart
+++ b/packages/flutter/test/painting/image_provider_test.dart
@@ -15,8 +15,8 @@
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 
+import '../image_data.dart';
 import '../rendering/rendering_tester.dart';
-import 'image_data.dart';
 import 'mocks_for_image_cache.dart';
 
 void main() {
@@ -149,7 +149,7 @@
 
   test('File image sets tag', () async {
     final MemoryFileSystem fs = MemoryFileSystem();
-    final File file = fs.file('/blue.png')..createSync(recursive: true)..writeAsBytesSync(kBlueRectPng);
+    final File file = fs.file('/blue.png')..createSync(recursive: true)..writeAsBytesSync(kBlueSquarePng);
     final FileImage provider = FileImage(file);
 
     final MultiFrameImageStreamCompleter completer = provider.load(provider, _decoder) as MultiFrameImageStreamCompleter;
@@ -158,7 +158,7 @@
   });
 
   test('Memory image sets tag', () async {
-    final Uint8List bytes = Uint8List.fromList(kBlueRectPng);
+    final Uint8List bytes = Uint8List.fromList(kBlueSquarePng);
     final MemoryImage provider = MemoryImage(bytes);
 
     final MultiFrameImageStreamCompleter completer = provider.load(provider, _decoder) as MultiFrameImageStreamCompleter;
@@ -176,7 +176,7 @@
   });
 
   test('Resize image sets tag', () async {
-    final Uint8List bytes = Uint8List.fromList(kBlueRectPng);
+    final Uint8List bytes = Uint8List.fromList(kBlueSquarePng);
     final ResizeImage provider = ResizeImage(MemoryImage(bytes), width: 40, height: 40);
     final MultiFrameImageStreamCompleter completer = provider.load(
       await provider.obtainKey(ImageConfiguration.empty),
@@ -206,6 +206,6 @@
 class _TestAssetBundle extends CachingAssetBundle {
   @override
   Future<ByteData> load(String key) async {
-    return Uint8List.fromList(kBlueRectPng).buffer.asByteData();
+    return Uint8List.fromList(kBlueSquarePng).buffer.asByteData();
   }
 }
diff --git a/packages/flutter/test/painting/image_test_utils.dart b/packages/flutter/test/painting/image_test_utils.dart
index e08a6db..082e8eb 100644
--- a/packages/flutter/test/painting/image_test_utils.dart
+++ b/packages/flutter/test/painting/image_test_utils.dart
@@ -5,13 +5,13 @@
 // @dart = 2.8
 
 import 'dart:async';
-import 'dart:typed_data';
 import 'dart:ui' as ui;
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/painting.dart';
 
-import 'image_data.dart';
+import 'package:flutter_test/flutter_test.dart';
+
 
 class TestImageProvider extends ImageProvider<TestImageProvider> {
   TestImageProvider(this.testImage);
@@ -49,12 +49,6 @@
   String toString() => '${describeIdentity(this)}()';
 }
 
-Future<ui.Image> createTestImage() {
-  final Completer<ui.Image> uiImage = Completer<ui.Image>();
-  ui.decodeImageFromList(Uint8List.fromList(kTransparentImage), uiImage.complete);
-  return uiImage.future;
-}
-
 class FakeImageConfiguration implements ImageConfiguration {
   @override
   dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
diff --git a/packages/flutter/test/painting/mocks_for_image_cache.dart b/packages/flutter/test/painting/mocks_for_image_cache.dart
index e6baec8..899254c 100644
--- a/packages/flutter/test/painting/mocks_for_image_cache.dart
+++ b/packages/flutter/test/painting/mocks_for_image_cache.dart
@@ -5,9 +5,7 @@
 // @dart = 2.8
 
 import 'dart:async';
-import 'dart:typed_data';
 import 'dart:ui' as ui show Image;
-import 'dart:ui';
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/painting.dart';
@@ -31,7 +29,7 @@
 }
 
 class TestImageProvider extends ImageProvider<int> {
-  const TestImageProvider(this.key, this.imageValue, { this.image = const TestImage() })
+  const TestImageProvider(this.key, this.imageValue, { @required this.image })
       : assert(image != null);
 
   final int key;
@@ -74,22 +72,6 @@
   return completer.future;
 }
 
-class TestImage implements ui.Image {
-  const TestImage({this.height = 0, this.width = 0});
-  @override
-  final int height;
-  @override
-  final int width;
-
-  @override
-  void dispose() { }
-
-  @override
-  Future<ByteData> toByteData({ ImageByteFormat format = ImageByteFormat.rawRgba }) {
-    throw UnimplementedError();
-  }
-}
-
 class ErrorImageProvider extends ImageProvider<ErrorImageProvider> {
   @override
   ImageStreamCompleter load(ErrorImageProvider key, DecoderCallback decode) {
@@ -141,7 +123,7 @@
 }
 
 class TestImageStreamCompleter extends ImageStreamCompleter {
-  void testSetImage(TestImage image) {
+  void testSetImage(ui.Image image) {
     setImage(ImageInfo(image: image, scale: 1.0));
   }
 }
diff --git a/packages/flutter/test/painting/paint_image_test.dart b/packages/flutter/test/painting/paint_image_test.dart
index 8ceb7b5..c046cfd 100644
--- a/packages/flutter/test/painting/paint_image_test.dart
+++ b/packages/flutter/test/painting/paint_image_test.dart
@@ -4,31 +4,12 @@
 
 // @dart = 2.8
 
-import 'dart:typed_data';
 import 'dart:ui' as ui;
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:flutter/painting.dart';
 
-class TestImage implements ui.Image {
-  TestImage({ this.width, this.height });
-
-  @override
-  final int width;
-
-  @override
-  final int height;
-
-  @override
-  void dispose() { }
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) async {
-    throw UnsupportedError('Cannot encode test image');
-  }
-}
-
 class TestCanvas implements Canvas {
   final List<Invocation> invocations = <Invocation>[];
 
@@ -39,17 +20,23 @@
 }
 
 void main() {
+  ui.Image image300x300;
+  ui.Image image300x200;
+  setUpAll(() async {
+    image300x300 = await createTestImage(width: 300, height: 300, cache: false);
+    image300x200 = await createTestImage(width: 300, height: 200, cache: false);
+  });
+
   setUp(() {
     debugFlushLastFrameImageSizeInfo();
   });
 
-  test('Cover and align', () {
-    final TestImage image = TestImage(width: 300, height: 300);
+  test('Cover and align', () async {
     final TestCanvas canvas = TestCanvas();
     paintImage(
       canvas: canvas,
       rect: const Rect.fromLTWH(50.0, 75.0, 200.0, 100.0),
-      image: image,
+      image: image300x300,
       fit: BoxFit.cover,
       alignment: const Alignment(-1.0, 0.0),
     );
@@ -59,12 +46,12 @@
     });
 
     expect(command, isNotNull);
-    expect(command.positionalArguments[0], equals(image));
+    expect(command.positionalArguments[0], equals(image300x300));
     expect(command.positionalArguments[1], equals(const Rect.fromLTWH(0.0, 75.0, 300.0, 150.0)));
     expect(command.positionalArguments[2], equals(const Rect.fromLTWH(50.0, 75.0, 200.0, 100.0)));
   });
 
-  test('debugInvertOversizedImages', () {
+  test('debugInvertOversizedImages', () async {
     debugInvertOversizedImages = true;
     final FlutterExceptionHandler oldFlutterError = FlutterError.onError;
 
@@ -73,14 +60,13 @@
       messages.add(details.exceptionAsString());
     };
 
-    final TestImage image = TestImage(width: 300, height: 300);
     final TestCanvas canvas = TestCanvas();
     const Rect rect = Rect.fromLTWH(50.0, 50.0, 200.0, 100.0);
 
     paintImage(
       canvas: canvas,
       rect: rect,
-      image: image,
+      image: image300x300,
       debugImageLabel: 'TestImage',
       fit: BoxFit.fill,
     );
@@ -132,12 +118,11 @@
       imageSizeInfo = info;
     };
 
-    final TestImage image = TestImage(width: 300, height: 300);
     final TestCanvas canvas = TestCanvas();
     paintImage(
       canvas: canvas,
       rect: const Rect.fromLTWH(50.0, 75.0, 200.0, 100.0),
-      image: image,
+      image: image300x300,
       debugImageLabel: 'test.png',
     );
 
@@ -155,7 +140,7 @@
     paintImage(
       canvas: canvas,
       rect: const Rect.fromLTWH(50.0, 75.0, 200.0, 100.0),
-      image: image,
+      image: image300x300,
       debugImageLabel: 'test.png',
     );
 
@@ -172,12 +157,11 @@
       imageSizeInfo = info;
     };
 
-    final TestImage image = TestImage(width: 300, height: 300);
     final TestCanvas canvas = TestCanvas();
     paintImage(
       canvas: canvas,
       rect: const Rect.fromLTWH(50.0, 75.0, 200.0, 100.0),
-      image: image,
+      image: image300x300,
       debugImageLabel: 'test.png',
     );
 
@@ -195,7 +179,7 @@
     paintImage(
       canvas: canvas,
       rect: const Rect.fromLTWH(50.0, 75.0, 200.0, 150.0),
-      image: image,
+      image: image300x300,
       debugImageLabel: 'test.png',
     );
 
@@ -216,12 +200,11 @@
       imageSizeInfo = info;
     };
 
-    final TestImage image = TestImage(width: 300, height: 200);
     final TestCanvas canvas = TestCanvas();
     paintImage(
       canvas: canvas,
       rect: const Rect.fromLTWH(50.0, 75.0, 200.0, 100.0),
-      image: image,
+      image: image300x200,
     );
 
     expect(count, 1);
diff --git a/packages/flutter/test/painting/shape_decoration_test.dart b/packages/flutter/test/painting/shape_decoration_test.dart
index 6222e5b..d472b9e 100644
--- a/packages/flutter/test/painting/shape_decoration_test.dart
+++ b/packages/flutter/test/painting/shape_decoration_test.dart
@@ -4,7 +4,6 @@
 
 // @dart = 2.8
 
-import 'dart:typed_data';
 import 'dart:ui' as ui;
 
 import 'package:flutter/foundation.dart';
@@ -59,12 +58,13 @@
     expect(b.hitTest(size, const Offset(20.0, 50.0)), isTrue);
   });
 
-  test('ShapeDecoration.image RTL test', () {
+  test('ShapeDecoration.image RTL test', () async {
+    final ui.Image image = await createTestImage(width: 100, height: 200);
     final List<int> log = <int>[];
     final ShapeDecoration decoration = ShapeDecoration(
       shape: const CircleBorder(),
       image: DecorationImage(
-        image: TestImageProvider(),
+        image: TestImageProvider(image),
         alignment: AlignmentDirectional.bottomEnd,
       ),
     );
@@ -113,6 +113,10 @@
 }
 
 class TestImageProvider extends ImageProvider<TestImageProvider> {
+  TestImageProvider(this.image);
+
+  final ui.Image image;
+
   @override
   Future<TestImageProvider> obtainKey(ImageConfiguration configuration) {
     return SynchronousFuture<TestImageProvider>(this);
@@ -121,23 +125,7 @@
   @override
   ImageStreamCompleter load(TestImageProvider key, DecoderCallback decode) {
     return OneFrameImageStreamCompleter(
-      SynchronousFuture<ImageInfo>(ImageInfo(image: TestImage(), scale: 1.0)),
+      SynchronousFuture<ImageInfo>(ImageInfo(image: image, scale: 1.0)),
     );
   }
 }
-
-class TestImage implements ui.Image {
-  @override
-  int get width => 100;
-
-  @override
-  int get height => 200;
-
-  @override
-  void dispose() { }
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) async {
-    throw UnsupportedError('Cannot encode test image');
-  }
-}
diff --git a/packages/flutter/test/rendering/image_test.dart b/packages/flutter/test/rendering/image_test.dart
index dce4dd9..504d44b 100644
--- a/packages/flutter/test/rendering/image_test.dart
+++ b/packages/flutter/test/rendering/image_test.dart
@@ -4,76 +4,22 @@
 
 // @dart = 2.8
 
-import 'dart:typed_data';
-import 'dart:ui' as ui show Image, ImageByteFormat;
+import 'dart:ui' as ui show Image;
 
+import 'package:flutter/foundation.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import 'rendering_tester.dart';
 
-class SquareImage implements ui.Image {
-  @override
-  int get width => 10;
-
-  @override
-  int get height => 10;
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) async {
-    throw UnsupportedError('Cannot encode test image');
-  }
-
-  @override
-  String toString() => '[$width\u00D7$height]';
-
-  @override
-  void dispose() { }
-}
-
-class WideImage implements ui.Image {
-  @override
-  int get width => 20;
-
-  @override
-  int get height => 10;
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) async {
-    throw UnsupportedError('Cannot encode test image');
-  }
-
-  @override
-  String toString() => '[$width\u00D7$height]';
-
-  @override
-  void dispose() { }
-}
-
-class TallImage implements ui.Image {
-  @override
-  int get width => 10;
-
-  @override
-  int get height => 20;
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) async {
-    throw UnsupportedError('Cannot encode test image');
-  }
-
-  @override
-  String toString() => '[$width\u00D7$height]';
-
-  @override
-  void dispose() { }
-}
-
-void main() {
+Future<void> main() async {
+  final ui.Image squareImage = await createTestImage(width: 10, height: 10);
+  final ui.Image wideImage =   await createTestImage(width: 20, height: 10);
+  final ui.Image tallImage =   await createTestImage(width: 10, height: 20);
   test('Image sizing', () {
     RenderImage image;
 
-    image = RenderImage(image: SquareImage());
+    image = RenderImage(image: squareImage);
     layout(image,
           constraints: const BoxConstraints(
               minWidth: 25.0,
@@ -83,7 +29,8 @@
     expect(image.size.width, equals(25.0));
     expect(image.size.height, equals(25.0));
 
-    expect(image, hasAGoodToStringDeep);
+    // TODO(dnfield): https://github.com/flutter/flutter/issues/66289
+    expect(image, hasAGoodToStringDeep, skip: kIsWeb);
     expect(
       image.toStringDeep(minLevel: DiagnosticLevel.info),
       equalsIgnoringHashCodes(
@@ -91,14 +38,14 @@
         '   parentData: <none> (can use size)\n'
         '   constraints: BoxConstraints(25.0<=w<=100.0, 25.0<=h<=100.0)\n'
         '   size: Size(25.0, 25.0)\n'
-        '   image: [10×10]\n'
+        '   image: $squareImage\n'
         '   alignment: center\n'
         '   invertColors: false\n'
         '   filterQuality: low\n'
       ),
     );
 
-    image = RenderImage(image: WideImage());
+    image = RenderImage(image: wideImage);
     layout(image,
            constraints: const BoxConstraints(
               minWidth: 5.0,
@@ -108,7 +55,7 @@
     expect(image.size.width, equals(60.0));
     expect(image.size.height, equals(30.0));
 
-    image = RenderImage(image: TallImage());
+    image = RenderImage(image: tallImage);
     layout(image,
            constraints: const BoxConstraints(
               minWidth: 50.0,
@@ -118,7 +65,7 @@
     expect(image.size.width, equals(50.0));
     expect(image.size.height, equals(75.0));
 
-    image = RenderImage(image: WideImage());
+    image = RenderImage(image: wideImage);
     layout(image,
            constraints: const BoxConstraints(
               minWidth: 5.0,
@@ -128,7 +75,7 @@
     expect(image.size.width, equals(20.0));
     expect(image.size.height, equals(10.0));
 
-    image = RenderImage(image: WideImage());
+    image = RenderImage(image: wideImage);
     layout(image,
            constraints: const BoxConstraints(
               minWidth: 5.0,
@@ -138,7 +85,7 @@
     expect(image.size.width, equals(16.0));
     expect(image.size.height, equals(8.0));
 
-    image = RenderImage(image: TallImage());
+    image = RenderImage(image: tallImage);
     layout(image,
            constraints: const BoxConstraints(
               minWidth: 5.0,
@@ -148,7 +95,7 @@
     expect(image.size.width, equals(8.0));
     expect(image.size.height, equals(16.0));
 
-    image = RenderImage(image: SquareImage());
+    image = RenderImage(image: squareImage);
     layout(image,
            constraints: const BoxConstraints(
               minWidth: 4.0,
@@ -158,7 +105,7 @@
     expect(image.size.width, equals(8.0));
     expect(image.size.height, equals(8.0));
 
-    image = RenderImage(image: WideImage());
+    image = RenderImage(image: wideImage);
     layout(image,
            constraints: const BoxConstraints(
               minWidth: 20.0,
@@ -168,7 +115,7 @@
     expect(image.size.width, equals(30.0));
     expect(image.size.height, equals(20.0));
 
-    image = RenderImage(image: TallImage());
+    image = RenderImage(image: tallImage);
     layout(image,
            constraints: const BoxConstraints(
               minWidth: 20.0,
diff --git a/packages/flutter/test/widgets/box_decoration_test.dart b/packages/flutter/test/widgets/box_decoration_test.dart
index 3cfacf2..fdd9da6 100644
--- a/packages/flutter/test/widgets/box_decoration_test.dart
+++ b/packages/flutter/test/widgets/box_decoration_test.dart
@@ -15,7 +15,7 @@
 import 'package:flutter/widgets.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import '../painting/image_data.dart';
+import '../image_data.dart';
 import '../rendering/mock_canvas.dart';
 
 class TestImageProvider extends ImageProvider<TestImageProvider> {
diff --git a/packages/flutter/test/widgets/fade_in_image_test.dart b/packages/flutter/test/widgets/fade_in_image_test.dart
index dc0505c..4277938 100644
--- a/packages/flutter/test/widgets/fade_in_image_test.dart
+++ b/packages/flutter/test/widgets/fade_in_image_test.dart
@@ -10,7 +10,8 @@
 import 'package:flutter/widgets.dart';
 import 'package:flutter/painting.dart';
 import 'package:flutter_test/flutter_test.dart';
-import '../painting/image_data.dart';
+
+import '../image_data.dart';
 import '../painting/image_test_utils.dart';
 
 const Duration animationDuration = Duration(milliseconds: 50);
diff --git a/packages/flutter/test/widgets/image_data.dart b/packages/flutter/test/widgets/image_data.dart
deleted file mode 100644
index 46a898b..0000000
--- a/packages/flutter/test/widgets/image_data.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// @dart = 2.8
-
-const List<int> kTransparentImage = <int>[
-  0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49,
-  0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06,
-  0x00, 0x00, 0x00, 0x1F, 0x15, 0xC4, 0x89, 0x00, 0x00, 0x00, 0x0A, 0x49, 0x44,
-  0x41, 0x54, 0x78, 0x9C, 0x63, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x01, 0x0D,
-  0x0A, 0x2D, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE,
-];
-
-/// An animated GIF image with 3 1x1 pixel frames (a red, green, and blue
-/// frames). The GIF animates forever, and each frame has a 100ms delay.
-const List<int> kAnimatedGif = <int> [
-  0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0xa1, 0x03, 0x00,
-  0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x21,
-  0xff, 0x0b, 0x4e, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e, 0x30,
-  0x03, 0x01, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x0a, 0x00, 0xff, 0x00,
-  0x2c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x4c,
-  0x01, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x0a, 0x00, 0xff, 0x00, 0x2c, 0x00, 0x00,
-  0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x54, 0x01, 0x00, 0x21,
-  0xf9, 0x04, 0x00, 0x0a, 0x00, 0xff, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b,
-];
diff --git a/packages/flutter/test/widgets/image_headers_test.dart b/packages/flutter/test/widgets/image_headers_test.dart
index b6a630a..ad4dba2 100644
--- a/packages/flutter/test/widgets/image_headers_test.dart
+++ b/packages/flutter/test/widgets/image_headers_test.dart
@@ -11,7 +11,7 @@
 import 'package:flutter_test/flutter_test.dart';
 
 import '../flutter_test_alternative.dart' show Fake;
-import '../painting/image_data.dart';
+import '../image_data.dart';
 
 void main() {
   final MockHttpClient client = MockHttpClient();
diff --git a/packages/flutter/test/widgets/image_icon_test.dart b/packages/flutter/test/widgets/image_icon_test.dart
index 2a8f8d5..68c4c45 100644
--- a/packages/flutter/test/widgets/image_icon_test.dart
+++ b/packages/flutter/test/widgets/image_icon_test.dart
@@ -10,13 +10,22 @@
 
 import '../painting/mocks_for_image_cache.dart';
 
-const ImageProvider _kImage = TestImageProvider(21, 42);
 
 void main() {
+  ImageProvider _image;
+
+  setUpAll(() async {
+    _image = TestImageProvider(
+      21,
+      42,
+      image: await createTestImage(width: 10, height: 10),
+    );
+  });
+
   testWidgets('ImageIcon sizing - no theme, default size', (WidgetTester tester) async {
     await tester.pumpWidget(
-      const Center(
-        child: ImageIcon(_kImage),
+      Center(
+        child: ImageIcon(_image),
       ),
     );
 
@@ -27,10 +36,10 @@
 
   testWidgets('Icon opacity', (WidgetTester tester) async {
     await tester.pumpWidget(
-      const Center(
+      Center(
         child: IconTheme(
-          data: IconThemeData(opacity: 0.5),
-          child: ImageIcon(_kImage),
+          data: const IconThemeData(opacity: 0.5),
+          child: ImageIcon(_image),
         ),
       ),
     );
diff --git a/packages/flutter/test/widgets/image_resolution_test.dart b/packages/flutter/test/widgets/image_resolution_test.dart
index 02ff2b9..d6b4611 100644
--- a/packages/flutter/test/widgets/image_resolution_test.dart
+++ b/packages/flutter/test/widgets/image_resolution_test.dart
@@ -6,7 +6,7 @@
 
 @TestOn('!chrome') // asset bundle behaves differently.
 import 'dart:typed_data';
-import 'dart:ui' as ui show Image, ImageByteFormat;
+import 'dart:ui' as ui show Image;
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/rendering.dart';
@@ -14,26 +14,7 @@
 import 'package:flutter/widgets.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import 'image_data.dart';
-
-class TestImage implements ui.Image {
-  TestImage(this.scale);
-  final double scale;
-
-  @override
-  int get width => (48*scale).floor();
-
-  @override
-  int get height => (48*scale).floor();
-
-  @override
-  void dispose() { }
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) async {
-    throw UnsupportedError('Cannot encode test image');
-  }
-}
+import '../image_data.dart';
 
 class TestByteData implements ByteData {
   TestByteData(this.scale);
@@ -104,14 +85,17 @@
 }
 
 class TestAssetImage extends AssetImage {
-  const TestAssetImage(String name) : super(name);
+  const TestAssetImage(String name, this.images) : super(name);
+
+  final Map<double, ui.Image> images;
 
   @override
   ImageStreamCompleter load(AssetBundleImageKey key, DecoderCallback decode) {
     ImageInfo imageInfo;
     key.bundle.load(key.name).then<void>((ByteData data) {
       final TestByteData testData = data as TestByteData;
-      final ui.Image image = TestImage(testData.scale);
+      final ui.Image image = images[testData.scale];
+      assert(image != null, 'Expected ${testData.scale} to have a key in $images');
       imageInfo = ImageInfo(image: image, scale: key.scale);
     });
     assert(imageInfo != null);
@@ -121,7 +105,7 @@
   }
 }
 
-Widget buildImageAtRatio(String image, Key key, double ratio, bool inferSize, [ AssetBundle bundle ]) {
+Widget buildImageAtRatio(String imageName, Key key, double ratio, bool inferSize, Map<double, ui.Image> images, [ AssetBundle bundle ]) {
   const double windowSize = 500.0; // 500 logical pixels
   const double imageSize = 200.0; // 200 logical pixels
 
@@ -138,12 +122,12 @@
           Image(
             key: key,
             excludeFromSemantics: true,
-            image: TestAssetImage(image),
+            image: TestAssetImage(imageName, images),
           ) :
           Image(
             key: key,
             excludeFromSemantics: true,
-            image: TestAssetImage(image),
+            image: TestAssetImage(imageName, images),
             height: imageSize,
             width: imageSize,
             fit: BoxFit.fill,
@@ -180,9 +164,6 @@
 RenderImage getRenderImage(WidgetTester tester, Key key) {
   return tester.renderObject<RenderImage>(find.byKey(key));
 }
-TestImage getTestImage(WidgetTester tester, Key key) {
-  return tester.renderObject<RenderImage>(find.byKey(key)).image as TestImage;
-}
 
 Future<void> pumpTreeToLayout(WidgetTester tester, Widget widget) {
   const Duration pumpDuration = Duration(milliseconds: 0);
@@ -193,88 +174,96 @@
 void main() {
   const String image = 'assets/image.png';
 
+  final Map<double, ui.Image> images = <double, ui.Image>{};
+  setUpAll(() async {
+    for (final double scale in const <double>[0.5, 1.0, 1.5, 2.0, 4.0, 10.0]) {
+      final int dimension = (48 * scale).floor();
+      images[scale] = await createTestImage(width: dimension, height: dimension);
+    }
+  });
+
   testWidgets('Image for device pixel ratio 1.0', (WidgetTester tester) async {
     const double ratio = 1.0;
     Key key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
     expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
-    expect(getTestImage(tester, key).scale, 1.0);
+    expect(getRenderImage(tester, key).scale, 1.0);
     key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, images));
     expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
-    expect(getTestImage(tester, key).scale, 1.0);
+    expect(getRenderImage(tester, key).scale, 1.0);
   });
 
   testWidgets('Image for device pixel ratio 0.5', (WidgetTester tester) async {
     const double ratio = 0.5;
     Key key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
     expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
-    expect(getTestImage(tester, key).scale, 1.0);
+    expect(getRenderImage(tester, key).scale, 1.0);
     key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, images));
     expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
-    expect(getTestImage(tester, key).scale, 1.0);
+    expect(getRenderImage(tester, key).scale, 1.0);
   });
 
   testWidgets('Image for device pixel ratio 1.5', (WidgetTester tester) async {
     const double ratio = 1.5;
     Key key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
     expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
-    expect(getTestImage(tester, key).scale, 1.5);
+    expect(getRenderImage(tester, key).scale, 1.5);
     key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, images));
     expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
-    expect(getTestImage(tester, key).scale, 1.5);
+    expect(getRenderImage(tester, key).scale, 1.5);
   });
 
   testWidgets('Image for device pixel ratio 1.75', (WidgetTester tester) async {
     const double ratio = 1.75;
     Key key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
     expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
-    expect(getTestImage(tester, key).scale, 1.5);
+    expect(getRenderImage(tester, key).scale, 1.5);
     key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, images));
     expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
-    expect(getTestImage(tester, key).scale, 1.5);
+    expect(getRenderImage(tester, key).scale, 1.5);
   });
 
   testWidgets('Image for device pixel ratio 2.3', (WidgetTester tester) async {
     const double ratio = 2.3;
     Key key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
     expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
-    expect(getTestImage(tester, key).scale, 2.0);
+    expect(getRenderImage(tester, key).scale, 2.0);
     key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, images));
     expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
-    expect(getTestImage(tester, key).scale, 2.0);
+    expect(getRenderImage(tester, key).scale, 2.0);
   });
 
   testWidgets('Image for device pixel ratio 3.7', (WidgetTester tester) async {
     const double ratio = 3.7;
     Key key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
     expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
-    expect(getTestImage(tester, key).scale, 4.0);
+    expect(getRenderImage(tester, key).scale, 4.0);
     key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, images));
     expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
-    expect(getTestImage(tester, key).scale, 4.0);
+    expect(getRenderImage(tester, key).scale, 4.0);
   });
 
   testWidgets('Image for device pixel ratio 5.1', (WidgetTester tester) async {
     const double ratio = 5.1;
     Key key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images));
     expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
-    expect(getTestImage(tester, key).scale, 4.0);
+    expect(getRenderImage(tester, key).scale, 4.0);
     key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, images));
     expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
-    expect(getTestImage(tester, key).scale, 4.0);
+    expect(getRenderImage(tester, key).scale, 4.0);
   });
 
   testWidgets('Image for device pixel ratio 1.0, with no main asset', (WidgetTester tester) async {
@@ -292,13 +281,13 @@
 
     const double ratio = 1.0;
     Key key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, bundle));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images, bundle));
     expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
-    expect(getTestImage(tester, key).scale, 1.5);
+    expect(getRenderImage(tester, key).scale, 1.5);
     key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, bundle));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, images, bundle));
     expect(getRenderImage(tester, key).size, const Size(48.0, 48.0));
-    expect(getTestImage(tester, key).scale, 1.5);
+    expect(getRenderImage(tester, key).scale, 1.5);
   });
 
   testWidgets('Image for device pixel ratio 1.0, with a main asset and a 1.0x asset', (WidgetTester tester) async {
@@ -321,13 +310,15 @@
 
     const double ratio = 1.0;
     Key key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, bundle));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, false, images, bundle));
     expect(getRenderImage(tester, key).size, const Size(200.0, 200.0));
-    expect(getTestImage(tester, key).scale, 10.0);
+    // Verify we got the 10x scaled image, since the TestByteData said it should be 10x.
+    expect(getRenderImage(tester, key).image.height, 480);
     key = GlobalKey();
-    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, bundle));
+    await pumpTreeToLayout(tester, buildImageAtRatio(image, key, ratio, true, images, bundle));
     expect(getRenderImage(tester, key).size, const Size(480.0, 480.0));
-    expect(getTestImage(tester, key).scale, 10.0);
+    // Verify we got the 10x scaled image, since the TestByteData said it should be 10x.
+    expect(getRenderImage(tester, key).image.height, 480);
   });
 
   testWidgets('Image cache resize upscale display 5', (WidgetTester tester) async {
diff --git a/packages/flutter/test/widgets/image_rtl_test.dart b/packages/flutter/test/widgets/image_rtl_test.dart
index 584cb03..f96593b 100644
--- a/packages/flutter/test/widgets/image_rtl_test.dart
+++ b/packages/flutter/test/widgets/image_rtl_test.dart
@@ -4,8 +4,7 @@
 
 // @dart = 2.8
 
-import 'dart:typed_data';
-import 'dart:ui' as ui show Image, ImageByteFormat;
+import 'dart:ui' as ui show Image;
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/widgets.dart';
@@ -14,6 +13,10 @@
 import '../rendering/mock_canvas.dart';
 
 class TestImageProvider extends ImageProvider<TestImageProvider> {
+  const TestImageProvider(this.image);
+
+  final ui.Image image;
+
   @override
   Future<TestImageProvider> obtainKey(ImageConfiguration configuration) {
     return SynchronousFuture<TestImageProvider>(this);
@@ -22,28 +25,16 @@
   @override
   ImageStreamCompleter load(TestImageProvider key, DecoderCallback decode) {
     return OneFrameImageStreamCompleter(
-      SynchronousFuture<ImageInfo>(ImageInfo(image: TestImage()))
+      SynchronousFuture<ImageInfo>(ImageInfo(image: image)),
     );
   }
 }
 
-class TestImage implements ui.Image {
-  @override
-  int get width => 16;
-
-  @override
-  int get height => 9;
-
-  @override
-  void dispose() { }
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) async {
-    throw UnsupportedError('Cannot encode test image');
-  }
-}
-
 void main() {
+  ui.Image testImage;
+  setUpAll(() async {
+    testImage = await createTestImage(width: 16, height: 9);
+  });
   testWidgets('DecorationImage RTL with alignment topEnd and match', (WidgetTester tester) async {
     await tester.pumpWidget(
       Directionality(
@@ -54,7 +45,7 @@
             height: 50.0,
             decoration: BoxDecoration(
               image: DecorationImage(
-                image: TestImageProvider(),
+                image: TestImageProvider(testImage),
                 alignment: AlignmentDirectional.topEnd,
                 repeat: ImageRepeat.repeatX,
                 matchTextDirection: true,
@@ -93,7 +84,7 @@
             height: 50.0,
             decoration: BoxDecoration(
               image: DecorationImage(
-                image: TestImageProvider(),
+                image: TestImageProvider(testImage),
                 alignment: AlignmentDirectional.topEnd,
                 repeat: ImageRepeat.repeatX,
                 matchTextDirection: true,
@@ -129,7 +120,7 @@
             height: 50.0,
             decoration: BoxDecoration(
               image: DecorationImage(
-                image: TestImageProvider(),
+                image: TestImageProvider(testImage),
                 alignment: AlignmentDirectional.topEnd,
                 repeat: ImageRepeat.repeatX,
               ),
@@ -164,7 +155,7 @@
             height: 50.0,
             decoration: BoxDecoration(
               image: DecorationImage(
-                image: TestImageProvider(),
+                image: TestImageProvider(testImage),
                 alignment: AlignmentDirectional.topEnd,
                 repeat: ImageRepeat.repeatX,
               ),
@@ -199,7 +190,7 @@
             height: 50.0,
             decoration: BoxDecoration(
               image: DecorationImage(
-                image: TestImageProvider(),
+                image: TestImageProvider(testImage),
                 alignment: Alignment.centerRight,
                 matchTextDirection: true,
               ),
@@ -231,7 +222,7 @@
             height: 50.0,
             decoration: BoxDecoration(
               image: DecorationImage(
-                image: TestImageProvider(),
+                image: TestImageProvider(testImage),
                 alignment: Alignment.centerRight,
               ),
             ),
@@ -258,7 +249,7 @@
             height: 50.0,
             decoration: BoxDecoration(
               image: DecorationImage(
-                image: TestImageProvider(),
+                image: TestImageProvider(testImage),
                 alignment: Alignment.centerRight,
                 matchTextDirection: true,
               ),
@@ -286,7 +277,7 @@
             height: 50.0,
             decoration: BoxDecoration(
               image: DecorationImage(
-                image: TestImageProvider(),
+                image: TestImageProvider(testImage),
                 alignment: Alignment.centerRight,
                 matchTextDirection: true,
               ),
@@ -313,7 +304,7 @@
             width: 100.0,
             height: 50.0,
             child: Image(
-              image: TestImageProvider(),
+              image: TestImageProvider(testImage),
               alignment: AlignmentDirectional.topEnd,
               repeat: ImageRepeat.repeatX,
               matchTextDirection: true,
@@ -350,7 +341,7 @@
             width: 100.0,
             height: 50.0,
             child: Image(
-              image: TestImageProvider(),
+              image: TestImageProvider(testImage),
               alignment: AlignmentDirectional.topEnd,
               repeat: ImageRepeat.repeatX,
               matchTextDirection: true,
@@ -384,7 +375,7 @@
             width: 100.0,
             height: 50.0,
             child: Image(
-              image: TestImageProvider(),
+              image: TestImageProvider(testImage),
               alignment: AlignmentDirectional.topEnd,
               repeat: ImageRepeat.repeatX,
             ),
@@ -417,7 +408,7 @@
             width: 100.0,
             height: 50.0,
             child: Image(
-              image: TestImageProvider(),
+              image: TestImageProvider(testImage),
               alignment: AlignmentDirectional.topEnd,
               repeat: ImageRepeat.repeatX,
             ),
@@ -450,15 +441,13 @@
             width: 100.0,
             height: 50.0,
             child: Image(
-              image: TestImageProvider(),
+              image: TestImageProvider(testImage),
               alignment: Alignment.centerRight,
               matchTextDirection: true,
             ),
           ),
         ),
       ),
-      Duration.zero,
-      EnginePhase.layout, // so that we don't try to paint the fake images
     );
     expect(find.byType(Container), paints
       ..translate(x: 50.0, y: 0.0)
@@ -480,7 +469,7 @@
             width: 100.0,
             height: 50.0,
             child: Image(
-              image: TestImageProvider(),
+              image: TestImageProvider(testImage),
               alignment: Alignment.centerRight,
             ),
           ),
@@ -505,7 +494,7 @@
             width: 100.0,
             height: 50.0,
             child: Image(
-              image: TestImageProvider(),
+              image: TestImageProvider(testImage),
               alignment: Alignment.centerRight,
               matchTextDirection: true,
             ),
@@ -531,7 +520,7 @@
             width: 100.0,
             height: 50.0,
             child: Image(
-              image: TestImageProvider(),
+              image: TestImageProvider(testImage),
               alignment: Alignment.centerRight,
               matchTextDirection: true,
             ),
@@ -553,7 +542,7 @@
       Directionality(
         textDirection: TextDirection.ltr,
         child: Image(
-          image: TestImageProvider(),
+          image: TestImageProvider(testImage),
           alignment: Alignment.centerRight,
           matchTextDirection: false,
         ),
@@ -565,7 +554,7 @@
       Directionality(
         textDirection: TextDirection.ltr,
         child: Image(
-          image: TestImageProvider(),
+          image: TestImageProvider(testImage),
           alignment: AlignmentDirectional.centerEnd,
           matchTextDirection: true,
         ),
@@ -577,7 +566,7 @@
       Directionality(
         textDirection: TextDirection.ltr,
         child: Image(
-          image: TestImageProvider(),
+          image: TestImageProvider(testImage),
           alignment: Alignment.centerRight,
           matchTextDirection: false,
         ),
diff --git a/packages/flutter/test/widgets/image_test.dart b/packages/flutter/test/widgets/image_test.dart
index 67595a4..6922b67 100644
--- a/packages/flutter/test/widgets/image_test.dart
+++ b/packages/flutter/test/widgets/image_test.dart
@@ -15,24 +15,18 @@
 import 'package:flutter/widgets.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import '../painting/image_data.dart';
+import '../image_data.dart';
 import 'semantics_tester.dart';
 
-// This must be run with [WidgetTester.runAsync] since it performs real async
-// work.
-Future<ui.Image> createTestImage([List<int> bytes = kTransparentImage]) async {
-  final ui.Codec codec = await ui.instantiateImageCodec(Uint8List.fromList(bytes));
-  final ui.FrameInfo frameInfo = await codec.getNextFrame();
-  return frameInfo.image;
-}
-
 void main() {
   int originalCacheSize;
+  ui.Image image10x10;
 
-  setUp(() {
+  setUp(() async {
     originalCacheSize = imageCache.maximumSize;
     imageCache.clear();
     imageCache.clearLiveImages();
+    image10x10 = await createTestImage(width: 10, height: 10);
   });
 
   tearDown(() {
@@ -56,7 +50,7 @@
     RenderImage renderImage = key.currentContext.findRenderObject() as RenderImage;
     expect(renderImage.image, isNull);
 
-    imageProvider1.complete();
+    imageProvider1.complete(image10x10);
     await tester.idle(); // resolve the future from the image provider
     await tester.pump(null, EnginePhase.layout);
 
@@ -98,7 +92,7 @@
     RenderImage renderImage = key.currentContext.findRenderObject() as RenderImage;
     expect(renderImage.image, isNull);
 
-    imageProvider1.complete();
+    imageProvider1.complete(image10x10);
     await tester.idle(); // resolve the future from the image provider
     await tester.pump(null, EnginePhase.layout);
 
@@ -138,7 +132,7 @@
     RenderImage renderImage = key.currentContext.findRenderObject() as RenderImage;
     expect(renderImage.image, isNull);
 
-    imageProvider1.complete();
+    imageProvider1.complete(image10x10);
     await tester.idle(); // resolve the future from the image provider
     await tester.pump(null, EnginePhase.layout);
 
@@ -176,7 +170,7 @@
     RenderImage renderImage = key.currentContext.findRenderObject() as RenderImage;
     expect(renderImage.image, isNull);
 
-    imageProvider1.complete();
+    imageProvider1.complete(image10x10);
     await tester.idle(); // resolve the future from the image provider
     await tester.pump(null, EnginePhase.layout);
 
@@ -466,15 +460,19 @@
   });
 
   testWidgets('Verify Image stops listening to ImageStream', (WidgetTester tester) async {
+    final ui.Image image100x100 = await tester.runAsync(() async => createTestImage(width: 100, height: 100));
+    // Web does not override the toString, whereas VM does
+    final String imageString = image100x100.toString();
+
     final TestImageProvider imageProvider = TestImageProvider();
     await tester.pumpWidget(Image(image: imageProvider, excludeFromSemantics: true));
     final State<Image> image = tester.state/*State<Image>*/(find.byType(Image));
     expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(stream: ImageStream#00000(OneFrameImageStreamCompleter#00000, unresolved, 2 listeners), pixels: null, loadingProgress: null, frameNumber: null, wasSynchronouslyLoaded: false)'));
-    imageProvider.complete();
+    imageProvider.complete(image100x100);
     await tester.pump();
-    expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(stream: ImageStream#00000(OneFrameImageStreamCompleter#00000, [100×100] @ 1.0x, 1 listener), pixels: [100×100] @ 1.0x, loadingProgress: null, frameNumber: 0, wasSynchronouslyLoaded: false)'));
+    expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(stream: ImageStream#00000(OneFrameImageStreamCompleter#00000, $imageString @ 1.0x, 1 listener), pixels: $imageString @ 1.0x, loadingProgress: null, frameNumber: 0, wasSynchronouslyLoaded: false)'));
     await tester.pumpWidget(Container());
-    expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(lifecycle state: defunct, not mounted, stream: ImageStream#00000(OneFrameImageStreamCompleter#00000, [100×100] @ 1.0x, 0 listeners), pixels: [100×100] @ 1.0x, loadingProgress: null, frameNumber: 0, wasSynchronouslyLoaded: false)'));
+    expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(lifecycle state: defunct, not mounted, stream: ImageStream#00000(OneFrameImageStreamCompleter#00000, $imageString @ 1.0x, 0 listeners), pixels: $imageString @ 1.0x, loadingProgress: null, frameNumber: 0, wasSynchronouslyLoaded: false)'));
   });
 
   testWidgets('Stream completer errors can be listened to by attaching before resolving', (WidgetTester tester) async {
@@ -768,7 +766,7 @@
         }
       )
     );
-    provider.complete();
+    provider.complete(image10x10);
     await precache;
     expect(provider._lastResolvedConfiguration, isNotNull);
 
@@ -862,6 +860,7 @@
 
     final TestImageProvider imageProvider1 = TestImageProvider();
     final TestImageProvider imageProvider2 = TestImageProvider();
+    final ui.Image image100x100 = await tester.runAsync(() async => createTestImage(width: 100, height: 100));
 
     await tester.pumpWidget(
         Container(
@@ -877,8 +876,8 @@
     RenderImage renderImage = key.currentContext.findRenderObject() as RenderImage;
     expect(renderImage.image, isNull);
 
-    imageProvider1.complete();
-    imageProvider2.complete();
+    imageProvider1.complete(image10x10);
+    imageProvider2.complete(image100x100);
     await tester.idle(); // resolve the future from the image provider
     await tester.pump(null, EnginePhase.layout);
 
@@ -905,8 +904,8 @@
   });
 
   testWidgets('Image State can be reconfigured to use another image', (WidgetTester tester) async {
-    final Image image1 = Image(image: TestImageProvider()..complete(), width: 10.0, excludeFromSemantics: true);
-    final Image image2 = Image(image: TestImageProvider()..complete(), width: 20.0, excludeFromSemantics: true);
+    final Image image1 = Image(image: TestImageProvider()..complete(image10x10), width: 10.0, excludeFromSemantics: true);
+    final Image image2 = Image(image: TestImageProvider()..complete(image10x10), width: 20.0, excludeFromSemantics: true);
 
     final Column column = Column(children: <Widget>[image1, image2]);
     await tester.pumpWidget(column, null, EnginePhase.layout);
@@ -1014,7 +1013,6 @@
   });
 
   testWidgets('Image invokes frameBuilder with correct wasSynchronouslyLoaded=false', (WidgetTester tester) async {
-    final ui.Image image = await tester.runAsync(createTestImage);
     final TestImageStreamCompleter streamCompleter = TestImageStreamCompleter();
     final TestImageProvider imageProvider = TestImageProvider(streamCompleter: streamCompleter);
     int lastFrame;
@@ -1034,15 +1032,14 @@
     expect(lastFrame, isNull);
     expect(lastFrameWasSync, isFalse);
     expect(find.byType(RawImage), findsOneWidget);
-    streamCompleter.setData(imageInfo: ImageInfo(image: image));
+    streamCompleter.setData(imageInfo: ImageInfo(image: image10x10));
     await tester.pump();
     expect(lastFrame, 0);
     expect(lastFrameWasSync, isFalse);
   });
 
   testWidgets('Image invokes frameBuilder with correct wasSynchronouslyLoaded=true', (WidgetTester tester) async {
-    final ui.Image image = await tester.runAsync(createTestImage);
-    final TestImageStreamCompleter streamCompleter = TestImageStreamCompleter(ImageInfo(image: image));
+    final TestImageStreamCompleter streamCompleter = TestImageStreamCompleter(ImageInfo(image: image10x10));
     final TestImageProvider imageProvider = TestImageProvider(streamCompleter: streamCompleter);
     int lastFrame;
     bool lastFrameWasSync;
@@ -1061,7 +1058,7 @@
     expect(lastFrame, 0);
     expect(lastFrameWasSync, isTrue);
     expect(find.byType(RawImage), findsOneWidget);
-    streamCompleter.setData(imageInfo: ImageInfo(image: image));
+    streamCompleter.setData(imageInfo: ImageInfo(image: image10x10));
     await tester.pump();
     expect(lastFrame, 1);
     expect(lastFrameWasSync, isTrue);
@@ -1173,7 +1170,6 @@
   });
 
   testWidgets('Image invokes loadingBuilder on chunk event notification', (WidgetTester tester) async {
-    final ui.Image image = await tester.runAsync(createTestImage);
     final TestImageStreamCompleter streamCompleter = TestImageStreamCompleter();
     final TestImageProvider imageProvider = TestImageProvider(streamCompleter: streamCompleter);
     final List<ImageChunkEvent> chunkEvents = <ImageChunkEvent>[];
@@ -1208,7 +1204,7 @@
     expect(chunkEvents.length, 3);
     expect(find.text('loading 30 / 100'), findsOneWidget);
     expect(find.byType(RawImage), findsNothing);
-    streamCompleter.setData(imageInfo: ImageInfo(image: image));
+    streamCompleter.setData(imageInfo: ImageInfo(image: image10x10));
     await tester.pump();
     expect(chunkEvents.length, 4);
     expect(find.byType(Text), findsNothing);
@@ -1216,7 +1212,6 @@
   });
 
   testWidgets("Image doesn't rebuild on chunk events if loadingBuilder is null", (WidgetTester tester) async {
-    final ui.Image image = await tester.runAsync(createTestImage);
     final TestImageStreamCompleter streamCompleter = TestImageStreamCompleter();
     final TestImageProvider imageProvider = TestImageProvider(streamCompleter: streamCompleter);
 
@@ -1230,7 +1225,7 @@
     expect(tester.binding.hasScheduledFrame, isFalse);
     streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
     expect(tester.binding.hasScheduledFrame, isFalse);
-    streamCompleter.setData(imageInfo: ImageInfo(image: image));
+    streamCompleter.setData(imageInfo: ImageInfo(image: image10x10));
     expect(tester.binding.hasScheduledFrame, isTrue);
     await tester.pump();
     streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
@@ -1451,7 +1446,6 @@
   testWidgets('Same image provider in multiple parts of the tree, no cache room left', (WidgetTester tester) async {
     imageCache.maximumSize = 0;
 
-    final ui.Image image = await tester.runAsync(createTestImage);
     final TestImageProvider provider1 = TestImageProvider();
     final TestImageProvider provider2 = TestImageProvider();
 
@@ -1480,10 +1474,10 @@
     expect(provider1.loadCallCount, 1);
     expect(provider2.loadCallCount, 1);
 
-    provider1.complete(image);
+    provider1.complete(image10x10);
     await tester.idle();
 
-    provider2.complete(image);
+    provider2.complete(image10x10);
     await tester.idle();
 
     expect(imageCache.liveImageCount, 2);
@@ -1516,7 +1510,7 @@
         }
       )
     );
-    provider.complete();
+    provider.complete(image10x10);
     await precache;
 
     // Should have ended up with only a weak ref, not in cache because cache size is 0
@@ -1566,7 +1560,7 @@
         }
       )
     );
-    provider.complete();
+    provider.complete(image10x10);
     await precache;
 
     // Should have ended up in the cache and have a weak reference.
@@ -1644,7 +1638,7 @@
     Object caughtException;
     await tester.pumpWidget(
       Image(
-        image: const FailingImageProvider(failOnObtainKey: true, throws: 'threw'),
+        image: FailingImageProvider(failOnObtainKey: true, throws: 'threw', image: image10x10),
         errorBuilder: (BuildContext context, Object error, StackTrace stackTrace) {
           caughtException = error;
           return SizedBox.expand(key: errorKey);
@@ -1664,7 +1658,7 @@
     Object caughtException;
     await tester.pumpWidget(
       Image(
-        image: const FailingImageProvider(failOnLoad: true, throws: 'threw'),
+        image: FailingImageProvider(failOnLoad: true, throws: 'threw', image: image10x10),
         errorBuilder: (BuildContext context, Object error, StackTrace stackTrace) {
           caughtException = error;
           return SizedBox.expand(key: errorKey);
@@ -1681,8 +1675,8 @@
 
   testWidgets('no errorBuilder - failure reported to FlutterError', (WidgetTester tester) async {
     await tester.pumpWidget(
-      const Image(
-        image: FailingImageProvider(failOnLoad: true, throws: 'threw'),
+      Image(
+        image: FailingImageProvider(failOnLoad: true, throws: 'threw', image: image10x10),
       ),
     );
 
@@ -1736,7 +1730,7 @@
       imageSizeInfo = info;
     };
 
-    final ui.Image image = await tester.runAsync(() => createTestImage(kBlueRectPng));
+    final ui.Image image = await tester.runAsync(() => createTestImage(width: 100, height: 100));
     final TestImageStreamCompleter streamCompleter = TestImageStreamCompleter(
       ImageInfo(
         image: image,
@@ -1847,8 +1841,7 @@
     return _streamCompleter;
   }
 
-  void complete([ui.Image image]) {
-    image ??= TestImage();
+  void complete(ui.Image image) {
     _completer.complete(ImageInfo(image: image));
   }
 
@@ -1898,25 +1891,6 @@
   }
 }
 
-class TestImage implements ui.Image {
-  @override
-  int get width => 100;
-
-  @override
-  int get height => 100;
-
-  @override
-  void dispose() { }
-
-  @override
-  Future<ByteData> toByteData({ ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba }) async {
-    throw UnsupportedError('Cannot encode test image');
-  }
-
-  @override
-  String toString() => '[$width\u00D7$height]';
-}
-
 class DebouncingImageProvider extends ImageProvider<Object> {
   DebouncingImageProvider(this.imageProvider, this.seenKeys);
 
@@ -1949,14 +1923,17 @@
     this.failOnObtainKey = false,
     this.failOnLoad = false,
     @required this.throws,
+    @required this.image,
   }) : assert(failOnLoad != null),
        assert(failOnObtainKey != null),
        assert(failOnLoad == true || failOnObtainKey == true),
-       assert(throws != null);
+       assert(throws != null),
+       assert(image != null);
 
   final bool failOnObtainKey;
   final bool failOnLoad;
   final Object throws;
+  final ui.Image image;
 
   @override
   Future<int> obtainKey(ImageConfiguration configuration) {
@@ -1974,7 +1951,7 @@
     return OneFrameImageStreamCompleter(
       Future<ImageInfo>.value(
         ImageInfo(
-          image: TestImage(),
+          image: image,
           scale: 0,
         ),
       ),
diff --git a/packages/flutter/test/widgets/obscured_animated_image_test.dart b/packages/flutter/test/widgets/obscured_animated_image_test.dart
index 1a50c99..92629be 100644
--- a/packages/flutter/test/widgets/obscured_animated_image_test.dart
+++ b/packages/flutter/test/widgets/obscured_animated_image_test.dart
@@ -11,9 +11,9 @@
 import 'package:flutter/rendering.dart';
 import 'package:flutter_test/flutter_test.dart';
 
+import '../image_data.dart';
 import '../painting/fake_codec.dart';
 import '../painting/fake_image_provider.dart';
-import '../painting/image_data.dart';
 
 Future<void> main() async {
   final FakeCodec fakeCodec = await FakeCodec.fromData(Uint8List.fromList(kAnimatedGif));
diff --git a/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart b/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart
index a68e50c..47aedaf 100644
--- a/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart
+++ b/packages/flutter/test/widgets/scroll_aware_image_provider_test.dart
@@ -4,13 +4,21 @@
 
 // @dart = 2.8
 
+import 'dart:ui' as ui show Image;
+
 import 'package:flutter_test/flutter_test.dart';
 import 'package:flutter/widgets.dart';
 
 import '../painting/image_test_utils.dart';
-import '../painting/mocks_for_image_cache.dart' show TestImage;
 
 void main() {
+
+  ui.Image testImage;
+
+  setUpAll(() async {
+    testImage = await createTestImage(width: 10, height: 10);
+  });
+
   tearDown(() {
     imageCache.clear();
   });
@@ -28,7 +36,6 @@
     await tester.pumpWidget(TestWidget(key));
 
     final DisposableBuildContext context = DisposableBuildContext(key.currentState);
-    const TestImage testImage = TestImage(width: 10, height: 10);
     final TestImageProvider testImageProvider = TestImageProvider(testImage);
     final ScrollAwareImageProvider<TestImageProvider> imageProvider = ScrollAwareImageProvider<TestImageProvider>(
       context: context,
@@ -64,7 +71,6 @@
     ));
 
     final DisposableBuildContext context = DisposableBuildContext(key.currentState);
-    const TestImage testImage = TestImage(width: 10, height: 10);
     final TestImageProvider testImageProvider = TestImageProvider(testImage);
     final ScrollAwareImageProvider<TestImageProvider> imageProvider = ScrollAwareImageProvider<TestImageProvider>(
       context: context,
@@ -105,7 +111,6 @@
     ));
 
     final DisposableBuildContext context = DisposableBuildContext(keys.last.currentState);
-    const TestImage testImage = TestImage(width: 10, height: 10);
     final TestImageProvider testImageProvider = TestImageProvider(testImage);
     final ScrollAwareImageProvider<TestImageProvider> imageProvider = ScrollAwareImageProvider<TestImageProvider>(
       context: context,
@@ -163,7 +168,6 @@
     ));
 
     final DisposableBuildContext context = DisposableBuildContext(keys.last.currentState);
-    const TestImage testImage = TestImage(width: 10, height: 10);
     final TestImageProvider testImageProvider = TestImageProvider(testImage);
     final ScrollAwareImageProvider<TestImageProvider> imageProvider = ScrollAwareImageProvider<TestImageProvider>(
       context: context,
@@ -231,7 +235,6 @@
     ));
 
     final DisposableBuildContext context = DisposableBuildContext(keys.last.currentState);
-    const TestImage testImage = TestImage(width: 10, height: 10);
     final TestImageProvider testImageProvider = TestImageProvider(testImage);
     final ScrollAwareImageProvider<TestImageProvider> imageProvider = ScrollAwareImageProvider<TestImageProvider>(
       context: context,
@@ -297,7 +300,6 @@
     ));
 
     final DisposableBuildContext context = DisposableBuildContext(key.currentState);
-    const TestImage testImage = TestImage(width: 10, height: 10);
     final TestImageProvider testImageProvider = TestImageProvider(testImage);
     final ScrollAwareImageProvider<TestImageProvider> imageProvider = ScrollAwareImageProvider<TestImageProvider>(
       context: context,
@@ -349,7 +351,6 @@
     ));
 
     final DisposableBuildContext context = DisposableBuildContext(key.currentState);
-    const TestImage testImage = TestImage(width: 10, height: 10);
     final TestImageProvider testImageProvider = TestImageProvider(testImage);
     final ScrollAwareImageProvider<TestImageProvider> imageProvider = ScrollAwareImageProvider<TestImageProvider>(
       context: context,
@@ -369,7 +370,7 @@
     expect(imageCache.currentSize, 0);
 
     // Occupy the only slot in the cache with another image.
-    final TestImageProvider testImageProvider2 = TestImageProvider(const TestImage());
+    final TestImageProvider testImageProvider2 = TestImageProvider(testImage);
     testImageProvider2.complete();
     await precacheImage(testImageProvider2, context.context);
     expect(imageCache.containsKey(testImageProvider), false);
diff --git a/packages/flutter/test/widgets/shape_decoration_test.dart b/packages/flutter/test/widgets/shape_decoration_test.dart
index de5662d..5252590 100644
--- a/packages/flutter/test/widgets/shape_decoration_test.dart
+++ b/packages/flutter/test/widgets/shape_decoration_test.dart
@@ -10,7 +10,7 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-import '../painting/image_data.dart';
+import '../image_data.dart';
 import '../painting/mocks_for_image_cache.dart';
 import '../rendering/mock_canvas.dart';
 import 'test_border.dart' show TestBorder;
diff --git a/packages/flutter_test/lib/flutter_test.dart b/packages/flutter_test/lib/flutter_test.dart
index c6b05e7..ad6076b 100644
--- a/packages/flutter_test/lib/flutter_test.dart
+++ b/packages/flutter_test/lib/flutter_test.dart
@@ -56,6 +56,7 @@
 export 'src/finders.dart';
 export 'src/frame_timing_summarizer.dart';
 export 'src/goldens.dart';
+export 'src/image.dart';
 export 'src/matchers.dart';
 export 'src/nonconst.dart';
 export 'src/platform.dart';
diff --git a/packages/flutter_test/lib/src/image.dart b/packages/flutter_test/lib/src/image.dart
new file mode 100644
index 0000000..04f7306
--- /dev/null
+++ b/packages/flutter_test/lib/src/image.dart
@@ -0,0 +1,119 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:typed_data';
+import 'dart:ui' as ui;
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/painting.dart';
+
+import 'test_async_utils.dart';
+
+final Map<int, ui.Image> _cache = <int, ui.Image>{};
+
+/// Creates an arbitrarily sized image for testing.
+///
+/// If the [cache] parameter is set to true, the image will be cached for the
+/// rest of this suite. This is normally desirable, assuming a test suite uses
+/// images with the same dimensions in most tests, as it will save on memory
+/// usage and CPU time over the course of the suite. However, it should be
+/// avoided for images that are used only once in a test suite, especially if
+/// the image is large, as it will require holding on to the memory for that
+/// image for the duration of the suite.
+///
+/// This method requires real async work, and will not work properly in the
+/// [FakeAsync] zones set up by [testWidgets]. Typically, it should be invoked
+/// as a setup step before [testWidgets] are run, such as [setUp] or [setUpAll].
+/// If needed, it can be invoked using [WidgetTester.runAsync].
+Future<ui.Image> createTestImage({
+  int width = 1,
+  int height = 1,
+  bool cache = true,
+}) => TestAsyncUtils.guard(() async {
+  assert(width != null && width > 0);
+  assert(height != null && height > 0);
+  assert(cache != null);
+
+  final int cacheKey = hashValues(width, height);
+  if (cache && _cache.containsKey(cacheKey)) {
+    return _cache[cacheKey];
+  }
+
+  final ui.Image image = await _createImage(width, height);
+  if (cache) {
+    _cache[cacheKey] = image;
+  }
+  return image;
+});
+
+Future<ui.Image> _createImage(int width, int height) async {
+  if (kIsWeb) {
+    return await _webCreateTestImage(
+      width: width,
+      height: height,
+    );
+  }
+
+  final Completer<ui.Image> completer = Completer<ui.Image>();
+  ui.decodeImageFromPixels(
+    Uint8List.fromList(List<int>.filled(width * height * 4, 0, growable: false)),
+    width,
+    height,
+    ui.PixelFormat.rgba8888,
+    (ui.Image image) {
+      completer.complete(image);
+    },
+  );
+  return await completer.future;
+}
+
+/// Web doesn't support [decodeImageFromPixels]. Instead, generate a 1bpp BMP
+/// and just use [instantiateImageCodec].
+// TODO(dnfield): Remove this when https://github.com/flutter/flutter/issues/49244
+// is resolved.
+Future<ui.Image> _webCreateTestImage({
+  int width,
+  int height,
+}) async {
+  // See https://en.wikipedia.org/wiki/BMP_file_format for format examples.
+  final int bufferSize = 0x36 + (width * height);
+  final ByteData bmpData = ByteData(bufferSize);
+  // 'BM' header
+  bmpData.setUint8(0x00, 0x42);
+  bmpData.setUint8(0x01, 0x4D);
+  // Size of data
+  bmpData.setUint32(0x02, bufferSize, Endian.little);
+  // Offset where pixel array begins
+  bmpData.setUint32(0x0A, 0x36, Endian.little);
+  // Bytes in DIB header
+  bmpData.setUint32(0x0E, 0x28, Endian.little);
+  // width
+  bmpData.setUint32(0x12, width, Endian.little);
+  // height
+  bmpData.setUint32(0x16, height, Endian.little);
+  // Color panes
+  bmpData.setUint16(0x1A, 0x01, Endian.little);
+  // bpp
+  bmpData.setUint16(0x1C, 0x01, Endian.little);
+  // no compression
+  bmpData.setUint32(0x1E, 0x00, Endian.little);
+  // raw bitmap data size
+  bmpData.setUint32(0x22, width * height, Endian.little);
+  // print DPI width
+  bmpData.setUint32(0x26, width, Endian.little);
+  // print DPI height
+  bmpData.setUint32(0x2A, height, Endian.little);
+  // colors in the palette
+  bmpData.setUint32(0x2E, 0x00, Endian.little);
+  // important colors
+  bmpData.setUint32(0x32, 0x00, Endian.little);
+  // rest of data is zeroed as black pixels.
+
+  final ui.Codec codec = await ui.instantiateImageCodec(
+    bmpData.buffer.asUint8List(),
+  );
+  final ui.FrameInfo frameInfo = await codec.getNextFrame();
+  return frameInfo.image;
+}