Flutter测试延迟导入包组件时触发Deferred Not Loaded Error如何解决
Flutter 延迟导入(deferred import)内容测试解决方案
报错核心原因为测试执行时,延迟模块的loadLibrary()异步方法未执行完成就直接访问了模块内的类、函数、Widget,可通过以下三种方案解决:
方法1:测试前主动预加载延迟模块
在测试用例的setUp生命周期中主动触发目标延迟库的加载,等待异步完成后再执行测试逻辑,示例代码如下:
import 'package:flutter_test/flutter_test.dart'; import 'package:spitch/app/splashscreen.dart' deferred as splashscreen; void main() { // 所有测试执行前先预加载延迟模块 setUp(() async { await splashscreen.loadLibrary(); }); testWidgets('测试SplashScreen组件渲染逻辑', (tester) async { await tester.pumpWidget(MaterialApp(home: splashscreen.SplashScreen())); expect(find.byType(splashscreen.SplashScreen), findsOneWidget); }); }
方法2:封装延迟加载通用逻辑(生产/测试通用)
对延迟导入的组件、函数做一层通用封装,同时兼容生产环境加载兜底和测试场景的加载等待,示例代码如下:
import 'package:flutter/material.dart'; import 'package:spitch/app/splashscreen.dart' deferred as splashscreen; class DeferredSplashScreen extends StatelessWidget { const DeferredSplashScreen({super.key}); @override Widget build(BuildContext context) { return FutureBuilder( // loadLibrary为幂等方法,多次调用只会执行一次加载,Dart底层会自动缓存加载状态 future: splashscreen.loadLibrary(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return splashscreen.SplashScreen(); } // 加载中兜底组件,可自定义为占位图、骨架屏等 return const Center(child: CircularProgressIndicator()); }, ); } }
测试时直接使用封装后的组件,调用tester.pumpAndSettle()等待加载完成即可:
testWidgets('测试封装后的延迟组件', (tester) async { await tester.pumpWidget(const MaterialApp(home: DeferredSplashScreen())); // 等待异步加载逻辑执行完成 await tester.pumpAndSettle(); expect(find.byType(splashscreen.SplashScreen), findsOneWidget); });
方法3:单元测试场景下Mock延迟内容
如果仅需要测试依赖延迟模块的上层逻辑,不需要真实执行延迟模块内部代码,可以直接Mock对应模块的函数、类,跳过真实的loadLibrary()调用即可。
注意事项
- Dart的
loadLibrary()方法是幂等的,多次调用不会带来额外性能损耗 - 纯Dart单元测试、Flutter组件测试、集成测试均兼容上述方案,无需额外配置
- 集成测试场景优先使用方法2的封装逻辑,和生产环境运行行为保持一致
内容的提问来源于stack exchange,提问作者R2T8
相关产品推荐
相关产品推荐

