precacheTestImage function

Future<void> precacheTestImage(
  1. ImageProvider<Object> provider, {
  2. ImageConfiguration configuration = ImageConfiguration.empty,
  3. ImageErrorListener? onError,
})

Precaches an ImageProvider during testing.

In a widget test, image decoding operations (such as MemoryImage, NetworkImage, and ExactAssetImage) run asynchronously outside the test's FakeAsync zone.

Calling precacheTestImage resolves the image stream in a real async zone (via TestWidgetsFlutterBinding.runAsync), loading the decoded image into imageCache before the widget tree is pumped.

Can be called before WidgetTester.pumpWidget inside a testWidgets body, or inside setUp / setUpAll.

If onError is provided, it will be invoked if an error occurs while precaching. Otherwise, any error will complete the returned future with that error.

Implementation

Future<void> precacheTestImage(
  ImageProvider provider, {
  ImageConfiguration configuration = ImageConfiguration.empty,
  ImageErrorListener? onError,
}) {
  final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
  Object? caughtError;
  StackTrace? caughtStackTrace;

  Future<void> resolveImage() async {
    final completer = Completer<void>.sync();
    final ImageStream stream = provider.resolve(configuration);
    late final ImageStreamListener listener;
    listener = ImageStreamListener(
      (ImageInfo info, bool syncCall) {
        info.dispose();
        if (!completer.isCompleted) {
          stream.removeListener(listener);
          completer.complete();
        }
      },
      onError: (Object error, StackTrace? stackTrace) {
        if (!completer.isCompleted) {
          stream.removeListener(listener);
          if (onError != null) {
            onError(error, stackTrace);
          } else {
            caughtError = error;
            caughtStackTrace = stackTrace;
          }
          completer.complete();
        }
      },
    );
    stream.addListener(listener);
    await completer.future;
  }

  Future<void> doPrecache() async {
    await binding.runAsync<void>(resolveImage);
    if (caughtError != null) {
      Error.throwWithStackTrace(caughtError!, caughtStackTrace ?? StackTrace.current);
    }
  }

  return TestAsyncUtils.guard(doPrecache);
}