Flutter测试问题:拖动SliverList后无法找到SliverAppBar标题文本
问题:拖动SliverList后测试找不到SliverAppBar标题文本?
我正在为自己的SliverAppBar示例应用编写测试,但测试中拖动SliverList的第一项后,无法找到flexibleSpace中的标题文本“SliverAppBar”。
应用代码
import 'package:flutter/material.dart'; void main() { runApp(const StretchableSliverAppBar()); } class StretchableSliverAppBar extends StatefulWidget { const StretchableSliverAppBar({super.key}); @override State<StretchableSliverAppBar> createState() = _StretchableSliverAppBarState(); } class _StretchableSliverAppBarState extends State<StretchableSliverAppBar> { bool _stretch = true; @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: CustomScrollView( physics: const BouncingScrollPhysics(), slivers: <Widget>[ SliverAppBar( stretch: _stretch, onStretchTrigger: () async {}, expandedHeight: 200.0, flexibleSpace: const FlexibleSpaceBar( title: Text('SliverAppBar'), background: FlutterLogo(), ), ), SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( color: index.isOdd ? Colors.white : Colors.black12, height: 100.0, child: Center( child: Text('$index', textScaleFactor: 5), ), ); }, childCount: 20, ), ), ], ), )); } }
测试代码
import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:test_project/main.dart'; const Offset _kOffset = Offset(0.0, -200.0); void main() { testWidgets('SliverAppbar can be stretched', (WidgetTester tester) async { await tester.pumpWidget( const StretchableSliverAppBar(), ); expect(find.text('SliverAppBar'), findsOneWidget); expect(tester.getBottomLeft(find.text('SliverAppBar')).dy, 184.0); await tester.drag(find.text('0'), _kOffset, touchSlopY: 0, warnIfMissed: false); await tester.pump(); await tester.pump(const Duration(milliseconds: 500)); // Failing to find this text "SliverAppBar" expect(find.text('SliverAppBar'), findsOneWidget); }); }
测试报错信息
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════ The following TestFailure was thrown running a test: Expected: exactly one matching node in the widget tree Actual: _TextFinder:<zero widgets with text "SliverAppBar" (ignoring offstage widgets)> Which: means none were found but one was expected When the exception was thrown, this was the stack: #4 main.<anonymous closure> (file:///D:/Flutter_Projects/test_project/test/widget_test.dart:56:5) <asynchronous suspension> <asynchronous suspension> (elided one frame from package:stack_trace) This was caught by the test expectation on the following line: file:///D:/Flutter_Projects/test_project/test/widget_test.dart line 56 The test description was: SliverAppbar can be stretched ════════════════════════════════════════════════════════════════════════════════════════════════════ Test failed. See exception logs above. The test description was: SliverAppbar can be stretched ✖ SliverAppbar can be stretched
问题原因及解决方法
原因
当向上拖动SliverList时,SliverAppBar会收缩,默认情况下FlexibleSpaceBar的标题会在AppBar收缩到阈值后被标记为offstage(非舞台可见区域)。而Flutter测试的find.text()方法默认参数skipOffstage: true,会自动忽略不在可见区域的widget,因此找不到该文本。
解决方法
有几种方式可以修复这个测试:
修改查找逻辑,不忽略offstage widget
调整查找语句,显式设置skipOffstage: false,这样就能找到即使不在可见区域的文本widget:expect(find.text('SliverAppBar', skipOffstage: false), findsOneWidget);调整拖动偏移量,避免标题隐藏
减小拖动的垂直偏移,让SliverAppBar不会收缩到标题隐藏的程度,比如把_kOffset改为:const Offset _kOffset = Offset(0.0, -100.0);这样标题会保持在可见区域,默认的查找逻辑就能找到它。
验证标题的可见性变化(可选)
如果测试目标是验证SliverAppBar收缩时标题的隐藏行为,可以分两步验证:// 默认忽略offstage,此时标题已隐藏,所以找不到 expect(find.text('SliverAppBar'), findsNothing); // 不忽略offstage,确认widget依然存在 expect(find.text('SliverAppBar', skipOffstage: false), findsOneWidget);
内容的提问来源于stack exchange,提问作者Istiak Ahmed
相关产品推荐
相关产品推荐

