Repository: flutter/flutter
File: packages/flutter/test/painting/image_provider_network_image_test.dart (Dart)

Code before:
  test('Network image with same arguments uses cache', () async {
    final _FakeHttpClient mockHttpClient = _FakeHttpClient();
    debugNetworkImageHttpClientProvider = () => mockHttpClient;
    mockHttpClient.request.response
      ..statusCode = HttpStatus.ok
      ..contentLength = kTransparentImage.length
      ..content = <Uint8List>[Uint8List.fromList(kTransparentImage)];

    final Completer<void> imageAvailable1 = Completer<void>();
    final ImageProvider imageProvider1 = NetworkImage(
      nonconst('testing.url'),
      headers: nonconst(<String, String>{'key': 'value'}),
    );
    expect(imageCache.liveImageCount, 0);

    final ImageStream result1 = imageProvider1.resolve(ImageConfiguration.empty);
    result1.addListener(
      ImageStreamListener((ImageInfo image, bool synchronousCall) {
        imageAvailable1.complete();
      }),
    );
    await imageAvailable1.future;
    expect(imageCache.liveImageCount, 1);

    // NetworkImage should not make another request.
    mockHttpClient.thrownError = Error();

    final Completer<void> imageAvailable2 = Completer<void>();
    final ImageProvider imageProvider2 = NetworkImage(
      nonconst('testing.url'),
      headers: nonconst(<String, String>{'key': 'value'}),
    );

    final ImageStream result2 = imageProvider2.resolve(ImageConfiguration.empty);
    result2.addListener(
      ImageStreamListener((ImageInfo image, bool synchronousCall) {
        imageAvailable2.complete();
      }),
    );
    await imageAvailable2.future;
    expect(imageCache.liveImageCount, 1);

    debugNetworkImageHttpClientProvider = null;
  }, skip: isBrowser); // [intended] Browser does not resolve images this way.

  test('Network image sets tag', () async {
    const String url = 'http://test.png';
    const int chunkSize = 8;
    final List<Uint8List> chunks = <Uint8List>[
      for (int offset = 0; offset < kTransparentImage.length; offset += chunkSize)
        Uint8List.fromList(kTransparentImage.skip(offset).take(chunkSize).toList()),

Review comment (bug):
This line doesn't totally reassure me that the test will notice if the NetworkImage does make another request. With the current implementation of _FakeHttpClient, that holds because `thrownError` takes precedence over `request`; but there's no reason it has to be that way, and someone could well refactor that in the future without noticing that it causes this test to be ineffective.

Let's instead put this in the same terms as the `.request.response` setup above, so that it clearly overrides it:

```suggestion
    // NetworkImage should not make another request.
    mockHttpClient.request.response.statusCode = HttpStatus.badRequest;
```

Alternatively, could set `debugNetworkImageHttpClientProvider` to a fresh _FakeHttpClient instance.


Code after:
  test('Network image with same arguments uses cache', () async {
    final _FakeHttpClient mockHttpClient = _FakeHttpClient();
    debugNetworkImageHttpClientProvider = () => mockHttpClient;
    mockHttpClient.request.response
      ..statusCode = HttpStatus.ok
      ..contentLength = kTransparentImage.length
      ..content = <Uint8List>[Uint8List.fromList(kTransparentImage)];

    final Completer<void> imageAvailable1 = Completer<void>();
    final ImageProvider imageProvider1 = NetworkImage(
      nonconst('testing.url'),
      headers: nonconst(<String, String>{'key': 'value'}),
    );
    expect(imageCache.liveImageCount, 0);

    final ImageStream result1 = imageProvider1.resolve(ImageConfiguration.empty);
    result1.addListener(
      ImageStreamListener((ImageInfo image, bool synchronousCall) {
        imageAvailable1.complete();
      }),
    );
    await imageAvailable1.future;
    expect(imageCache.liveImageCount, 1);

    // NetworkImage should not make another request.
    mockHttpClient.request.response.statusCode = HttpStatus.badRequest;

    final Completer<void> imageAvailable2 = Completer<void>();
    final ImageProvider imageProvider2 = NetworkImage(
      nonconst('testing.url'),
      headers: nonconst(<String, String>{'key': 'value'}),
    );

    final ImageStream result2 = imageProvider2.resolve(ImageConfiguration.empty);
    result2.addListener(
      ImageStreamListener((ImageInfo image, bool synchronousCall) {
        imageAvailable2.complete();
      }),
    );
    await imageAvailable2.future;
    expect(imageCache.liveImageCount, 1);

    debugNetworkImageHttpClientProvider = null;
  }, skip: isBrowser); // [intended] Browser does not resolve images this way.

  test('Network image sets tag', () async {
    const String url = 'http://test.png';
    const int chunkSize = 8;
    final List<Uint8List> chunks = <Uint8List>[
      for (int offset = 0; offset < kTransparentImage.length; offset += chunkSize)
        Uint8List.fromList(kTransparentImage.skip(offset).take(chunkSize).toList()),