Skip to content

Commit 88e49ed

Browse files
authored
Load assets in flutter_test without turning event loop. (#115123)
* Load assets in flutter_test without turning event loop. This makes it possible to load an asset without actually turning the event loop. This is importnat because our FakeAsync zones may cause people to sprinkle in extra pumpAndSettles in when running tests that load assets, which is undesirable. * fix null checking
1 parent 6e89042 commit 88e49ed

File tree

4 files changed

+30
-13
lines changed

4 files changed

+30
-13
lines changed

packages/flutter/lib/src/foundation/synchronous_future.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ class SynchronousFuture<T> implements Future<T> {
3838

3939
@override
4040
Future<R> then<R>(FutureOr<R> Function(T value) onValue, { Function? onError }) {
41-
final dynamic result = onValue(_value);
41+
final FutureOr<R> result = onValue(_value);
4242
if (result is Future<R>) {
4343
return result;
4444
}
45-
return SynchronousFuture<R>(result as R);
45+
return SynchronousFuture<R>(result);
4646
}
4747

4848
@override

packages/flutter/lib/src/services/asset_bundle.dart

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,17 +247,24 @@ abstract class CachingAssetBundle extends AssetBundle {
247247
/// An [AssetBundle] that loads resources using platform messages.
248248
class PlatformAssetBundle extends CachingAssetBundle {
249249
@override
250-
Future<ByteData> load(String key) async {
250+
Future<ByteData> load(String key) {
251251
final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull(key)).path);
252-
final ByteData? asset =
253-
await ServicesBinding.instance.defaultBinaryMessenger.send('flutter/assets', encoded.buffer.asByteData());
254-
if (asset == null) {
252+
final Future<ByteData>? future = ServicesBinding.instance.defaultBinaryMessenger.send('flutter/assets', encoded.buffer.asByteData())?.then((ByteData? asset) {
253+
if (asset == null) {
254+
throw FlutterError.fromParts(<DiagnosticsNode>[
255+
_errorSummaryWithKey(key),
256+
ErrorDescription('The asset does not exist or has empty data.'),
257+
]);
258+
}
259+
return asset;
260+
});
261+
if (future == null) {
255262
throw FlutterError.fromParts(<DiagnosticsNode>[
256-
_errorSummaryWithKey(key),
257-
ErrorDescription('The asset does not exist or has empty data.'),
258-
]);
263+
_errorSummaryWithKey(key),
264+
ErrorDescription('The asset does not exist or has empty data.'),
265+
]);
259266
}
260-
return asset;
267+
return future;
261268
}
262269

263270
@override

packages/flutter_test/lib/src/_binding_io.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import 'dart:async';
66
import 'dart:convert';
77
import 'dart:io';
88

9+
import 'package:flutter/foundation.dart';
910
import 'package:flutter/services.dart';
10-
import 'package:flutter/widgets.dart';
1111
import 'package:path/path.dart' as path;
1212
// ignore: deprecated_member_use
1313
import 'package:test_api/test_api.dart' as test_package;
@@ -42,7 +42,7 @@ void mockFlutterAssets() {
4242
/// platform messages.
4343
SystemChannels.navigation.setMockMethodCallHandler((MethodCall methodCall) async {});
4444

45-
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async {
45+
ServicesBinding.instance.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) {
4646
assert(message != null);
4747
String key = utf8.decode(message!.buffer.asUint8List());
4848
File asset = File(path.join(assetFolderPath, key));
@@ -62,7 +62,7 @@ void mockFlutterAssets() {
6262
}
6363

6464
final Uint8List encoded = Uint8List.fromList(asset.readAsBytesSync());
65-
return Future<ByteData>.value(encoded.buffer.asByteData());
65+
return SynchronousFuture<ByteData>(encoded.buffer.asByteData());
6666
});
6767
}
6868

packages/flutter_test/test/bindings_test.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import 'dart:async';
1111
import 'dart:io';
1212

13+
import 'package:flutter/services.dart';
1314
import 'package:flutter/widgets.dart';
1415
import 'package:flutter_test/flutter_test.dart';
1516

@@ -90,4 +91,13 @@ void main() {
9091
binding.idle();
9192
});
9293
});
94+
95+
testWidgets('Assets in the tester can be loaded without turning event loop', (WidgetTester tester) async {
96+
bool responded = false;
97+
// The particular asset does not matter, as long as it exists.
98+
rootBundle.load('AssetManifest.json').then((ByteData data) {
99+
responded = true;
100+
});
101+
expect(responded, true);
102+
});
93103
}

0 commit comments

Comments
 (0)