Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Have 404s from the fake HttpClient explain that tests don't hit the network but fake a 404 #13433

Closed
DaveShuckerow opened this issue Dec 7, 2017 · 15 comments
Labels
a: error message Error messages from the Flutter framework a: images Loading, displaying, rendering images a: tests "flutter test", flutter_test, or one of our tests framework flutter/packages/flutter repository. See also f: labels.

Comments

@DaveShuckerow
Copy link
Contributor

DaveShuckerow commented Dec 7, 2017

Steps to Reproduce

I'm loading a NetworkImage in a Flutter test, and it's failing with a 404 error. I've tried a number of different images that I can access from my browser, but the test is unable to load them.

Diff from flutter_markdown/master: https://github.com/flutter/flutter_markdown/compare/master...DaveShuckerow:image-fix

Any clue what might cause the error?

Logs

══╡ EXCEPTION CAUGHT BY SERVICES ╞══════════════════════════════════════════════════════════════════
The following _Exception was thrown resolving an image codec:
Exception: HTTP request failed, statusCode: 404,
https://pbs.twimg.com/profile_images/760249570085314560/yCrkrbl3.jpg

When the exception was thrown, this was the stack:
#0      NetworkImage._loadAsync (package:flutter/src/services/image_provider.dart:442:7)
<asynchronous suspension>
#1      NetworkImage.load (package:flutter/src/services/image_provider.dart:425:14)
#2      ImageProvider.resolve.<anonymous closure>.<anonymous closure> (package:flutter/src/services/image_provider.dart:265:61)
#3      ImageCache.putIfAbsent (package:flutter/src/services/image_cache.dart:82:22)
#4      ImageProvider.resolve.<anonymous closure> (package:flutter/src/services/image_provider.dart:265:38)
#5      SynchronousFuture.then (package:flutter/src/foundation/synchronous_future.dart:38:29)
#6      ImageProvider.resolve (package:flutter/src/services/image_provider.dart:263:30)
#7      _ImageState._resolveImage (package:flutter/src/widgets/image.dart:480:20)
#8      _ImageState.didChangeDependencies (package:flutter/src/widgets/image.dart:455:5)
#9      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3660:12)
#10     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
#11     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
#12     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:32)
#13     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
#14     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
#15     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
#16     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
#17     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
#18     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
#19     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
#20     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
#21     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
#22     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
#23     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
#24     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
#25     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
#26     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
#27     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
#28     ParentDataElement.mount (package:flutter/src/widgets/framework.dart:3837:16)
#29     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
#30     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
#31     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
#32     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
#33     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
#34     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
#35     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
#36     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
#37     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
#38     SliverMultiBoxAdaptorElement.createChild.<anonymous closure> (package:flutter/src/widgets/sliver.dart:723:20)
#39     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2173:19)
#40     SliverMultiBoxAdaptorElement.createChild (package:flutter/src/widgets/sliver.dart:716:11)
#41     RenderSliverMultiBoxAdaptor._createOrObtainChild.<anonymous closure> (package:flutter/src/rendering/sliver_multi_box_adaptor.dart:238:23)
#42     RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:1645:58)
#43     PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:734:15)
#44     RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:1645:13)
#45     RenderSliverMultiBoxAdaptor._createOrObtainChild (package:flutter/src/rendering/sliver_multi_box_adaptor.dart:227:5)
#46     RenderSliverMultiBoxAdaptor.addInitialChild (package:flutter/src/rendering/sliver_multi_box_adaptor.dart:335:5)
#47     RenderSliverList.performLayout (package:flutter/src/rendering/sliver_list.dart:78:12)
#48     RenderObject.layout (package:flutter/src/rendering/object.dart:1549:7)
#49     RenderSliverPadding.performLayout (package:flutter/src/rendering/sliver_padding.dart:182:11)
#50     RenderObject.layout (package:flutter/src/rendering/object.dart:1549:7)
#51     RenderViewportBase.layoutChildSequence (package:flutter/src/rendering/viewport.dart:287:13)
#52     RenderViewport._attemptLayout (package:flutter/src/rendering/viewport.dart:980:12)
#53     RenderViewport.performLayout (package:flutter/src/rendering/viewport.dart:904:20)
#54     RenderObject.layout (package:flutter/src/rendering/object.dart:1549:7)
#55     RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:106:13)
#56     RenderObject.layout (package:flutter/src/rendering/object.dart:1549:7)
#57     RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:106:13)
#58     RenderObject.layout (package:flutter/src/rendering/object.dart:1549:7)
#59     RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:106:13)
#60     RenderObject.layout (package:flutter/src/rendering/object.dart:1549:7)
#61     RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:106:13)
#62     RenderObject.layout (package:flutter/src/rendering/object.dart:1549:7)
#63     RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:106:13)
#64     RenderObject.layout (package:flutter/src/rendering/object.dart:1549:7)
#65     RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:106:13)
#66     RenderObject.layout (package:flutter/src/rendering/object.dart:1549:7)
#67     RenderView.performLayout (package:flutter/src/rendering/view.dart:142:13)
#68     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1424:7)
#69     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:712:18)
#70     AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:599:23)
#71     BindingBase&SchedulerBinding&GestureBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:200:5)
#72     BindingBase&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:713:15)
#73     BindingBase&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:649:9)
#74     AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:565:9)
#77     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:69:44)
#78     AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:553:27)
#79     WidgetTester.pumpWidget.<anonymous closure> (package:flutter_test/src/widget_tester.dart:192:22)
#82     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:69:44)
#83     WidgetTester.pumpWidget (package:flutter_test/src/widget_tester.dart:189:27)
#84     main.<anonymous closure> (///usr/local/google/home/djshuckerow/Open/github.com/DaveShuckerow/flutter_markdown/test/flutter_markdown_test.dart:170:18)
<asynchronous suspension>
#85     testWidgets.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:60:25)
#86     TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:464:19)
<asynchronous suspension>
#89     TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:451:14)
#90     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:632:24)
#96     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:630:16)
#97     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:59:24)
#98     Declarer.test.<anonymous closure>.<anonymous closure> (package:test/src/backend/declarer.dart:160:19)
<asynchronous suspension>
#99     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test/src/backend/invoker.dart:206:15)
<asynchronous suspension>
#103    Invoker.waitForOutstandingCallbacks (package:test/src/backend/invoker.dart:203:5)
#104    Declarer.test.<anonymous closure> (package:test/src/backend/declarer.dart:158:29)
<asynchronous suspension>
#105    Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test/src/backend/invoker.dart:351:23)
<asynchronous suspension>
#119    _Timer._runTimers (dart:isolate-patch/dart:isolate/timer_impl.dart:367)
#120    _Timer._handleMessage (dart:isolate-patch/dart:isolate/timer_impl.dart:401)
#121    _RawReceivePortImpl._handleMessage (dart:isolate-patch/dart:isolate/isolate_patch.dart:163)
(elided 27 frames from class _FakeAsync, package dart:async, package dart:async-patch, and package
stack_trace)

Image provider: NetworkImage("https://pbs.twimg.com/profile_images/760249570085314560/yCrkrbl3.jpg",
scale: 1.0)
Image key: NetworkImage("https://pbs.twimg.com/profile_images/760249570085314560/yCrkrbl3.jpg",
scale: 1.0)
════════════════════════════════════════════════════════════════════════════════════════════════════
00:01 +9 -1: - Image links [E]                                                                     
  Test failed. See exception logs above.
  The test description was: Image links
  
00:02 +15 -1: Some tests failed.   

Flutter Doctor

[✓] Flutter (on Linux, locale en_US.UTF-8, channel master)
    • Flutter at /<snip>/flutter
    • Framework revision 9315a79b11 (2 hours ago), 2017-12-07 13:31:32 -0800
    • Engine revision f888186e50
    • Tools Dart version 1.25.0-dev.11.0
    • Engine Dart version 2.0.0-edge.e7b7b68ef6e7b1e5df379b628134764c489901dc

For more information about diagnosing and reporting Flutter bugs, please see https://flutter.io/bug-reports/.

@tvolkert tvolkert added customer blocker a: tests "flutter test", flutter_test, or one of our tests labels Dec 7, 2017
@tvolkert
Copy link
Contributor

tvolkert commented Dec 7, 2017

/cc @Hixie @yjbanov

@yjbanov
Copy link
Contributor

yjbanov commented Dec 7, 2017

What happens when you run flutter test on the following?

import 'package:http/http.dart' as http;

main() async {
  var resp = await new http.Client().get('https://pbs.twimg.com/profile_images/760249570085314560/yCrkrbl3.jpg');
  print(resp.bodyBytes);
}

@yjbanov
Copy link
Contributor

yjbanov commented Dec 7, 2017

Also, could you try running the same code with plain dart executable (trying to eliminate differences in environments)?

@DaveShuckerow
Copy link
Contributor Author

What happens when you run flutter test on the following?

The code prints out the response bytes, and then reports that no tests ran:

[255, 216, 255, 224, 0, 16...

Running dart test also prints out the response bytes.

@yjbanov
Copy link
Contributor

yjbanov commented Dec 8, 2017

Probably this (i.e. by default we don't support loading images from the network in the test environment). You could overwrite createHttpClient with an implementation that performs real HTTP.

@yjbanov
Copy link
Contributor

yjbanov commented Dec 8, 2017

However, keep in mind that testWidgets runs inside FakeAsync, and real HTTP would be scheduling real async work. It could get messy (I'd even say likely).

@DaveShuckerow
Copy link
Contributor Author

I'd rather not do that if possible.

This is only an issue because a recent change made it an exception for the image to not load:
5fc8eb8#diff-a5ffc39bba0203b5795ee840e4678a89R435

I think this may break any test on a widget tree that contains a NetworkImage.

Because of that, I think the best approaches are either for NetworkImage to skip the responseCode check in tests or to revert that exception throwing entirely.

@yjbanov
Copy link
Contributor

yjbanov commented Dec 8, 2017

OIC. /cc @amirh

@amirh
Copy link
Contributor

amirh commented Dec 8, 2017

There's an example here, of how we override the http client in one of the Flutter tests so that it always returns an empty image:
https://github.com/flutter/flutter/blob/master/dev/manual_tests/test/mock_image_http.dart

Regarding not throwing for network image loading errors - I think it makes sense to propagate the failure and allow developers to handle it.
cc @Hixie who asked for these exceptions.

@Hixie
Copy link
Contributor

Hixie commented Dec 11, 2017

They're not technically exceptions, just errors that get reported to the error reporting mechanism, which the test framework interprets as a failure.

If you're ok with a 404, you can use takeException to say that you expect that one failure.

If you want to test with very specific images, you can do what @amirh mentions in his last comment.

@Hixie Hixie added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Dec 12, 2017
@Hixie Hixie added this to the 3: Current Milestone milestone Dec 12, 2017
@DaveShuckerow
Copy link
Contributor Author

For now, we faked the image client similarly to the framework code @amirh linked above does: https://github.com/flutter/flutter_markdown/pull/17

Request: To reduce friction for other users who run into this, would it be possible to add a line to the output of the test failure explaining that the http client is faked to always return 404s in Flutter tests?

@Hixie
Copy link
Contributor

Hixie commented Dec 15, 2017

Yeah, that makes a lot of sense.

@Hixie Hixie removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Dec 15, 2017
@Hixie Hixie changed the title NetworkImage http request fails crashing tests Have 404s from the fake HttpClient explain that tests don't hit the network but fake a 404 Dec 15, 2017
@Hixie Hixie modified the milestones: 3: Current Milestone, 5: Make Hixie proud Dec 15, 2017
@zoechi zoechi added the will need additional triage This issue or PR needs attention during weekly triage label Dec 3, 2018
@zoechi zoechi removed the will need additional triage This issue or PR needs attention during weekly triage label Dec 18, 2018
@iapicca iapicca added a: error message Error messages from the Flutter framework a: images Loading, displaying, rendering images dependency: dart Dart team may need to help us framework flutter/packages/flutter repository. See also f: labels. d: devtools DevTools related - suite of performance and debugging tools tool Affects the "flutter" command-line tool. See also t: labels. labels Jan 6, 2020
@Hixie Hixie removed this from the Stretch Goals milestone Jan 7, 2020
@Hixie Hixie added this to the New Stretch Goals milestone Jan 7, 2020
@jonahwilliams jonahwilliams removed dependency: dart Dart team may need to help us d: devtools DevTools related - suite of performance and debugging tools tool Affects the "flutter" command-line tool. See also t: labels. labels Jan 10, 2020
@jonahwilliams
Copy link
Member

Removing tool designation since this does not depend on the tool at all

@dnfield
Copy link
Contributor

dnfield commented Feb 25, 2020

This was fixed by #49844 and was duplicated in #35318

@dnfield dnfield closed this as completed Feb 25, 2020
@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: error message Error messages from the Flutter framework a: images Loading, displaying, rendering images a: tests "flutter test", flutter_test, or one of our tests framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

No branches or pull requests

9 participants