-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
There are some tests that use FakeAsync.run() that are not awaiting the call, for example:
flutter/packages/flutter_tools/test/general.shard/device_test.dart
Lines 92 to 95 in 0e735e4
| FakeAsync().run((FakeAsync time) async { | |
| final FakePollingDeviceDiscovery pollingDeviceDiscovery = FakePollingDeviceDiscovery(); | |
| await pollingDeviceDiscovery.startPolling(); | |
| time.elapse(const Duration(milliseconds: 4001)); |
It seems like this is resulted in the tests always passing immediately. For example adding throw 'fail'; as the first line inside the callback does nothing - the test still passes.
I think these tests need await in front of the FakeAsync().run, however doing so right now causes them to hang - which I think is because the implementation uses await which queues a microtask but the queue is never flushed (since the code stops on the await).
Based on what @Hixie said, I think flutter_test is handling this by constantly pumping the microtask queue, however the flutter_tools tests don't run with flutter_test so don't have an equivilent. I think the relevant code in flutter_test is this bit:
flutter/packages/flutter_test/lib/src/binding.dart
Lines 1128 to 1146 in 868c4d8
| return Future<void>.microtask(() async { | |
| // testBodyResult is a Future that was created in the Zone of the | |
| // fakeAsync. This means that if we await it here, it will register a | |
| // microtask to handle the future _in the fake async zone_. We avoid this | |
| // by calling '.then' in the current zone. While flushing the microtasks | |
| // of the fake-zone below, the new future will be completed and can then | |
| // be used without fakeAsync. | |
| final Future<void> resultFuture = testBodyResult.then<void>((_) { | |
| // Do nothing. | |
| }); | |
| // Resolve interplay between fake async and real async calls. | |
| fakeAsync.flushMicrotasks(); | |
| while (_pendingAsyncTasks != null) { | |
| await _pendingAsyncTasks.future; | |
| fakeAsync.flushMicrotasks(); | |
| } | |
| return resultFuture; | |
| }); |