在Flutter测试中查找CustomScrollView中的小部件

7
当我试图测试我的Flutter应用程序时,遇到了一个错误。我有一个自定义的小部件,位于CustomScrollView小部件的底部(超出第一个视口)。在我的测试中,我想验证它实际上是否存在。
我已经尝试使用WidgetTester.scrollUntilVisible以及WidgetTester.drag(就像在flutter框架的测试中所做的那样)。此外,我还尝试使用FlutterDriver重构我的测试,但这只是彻底搞砸了一切其他东西。
如何在测试中滚动到CustomScrollView的底部?
这个最小化的复制品显示了包含CustomScrollView的应用程序,它具有高度为一个屏幕的容器小部件(以便我想要查找的小部件超出了初始视图)。
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: CustomScrollView(
        slivers: [
          SliverToBoxAdapter(
            child: Container(
              height: MediaQuery.of(context).size.height,
            ),
          ),
          MyWidget(),
        ],
      )),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SliverToBoxAdapter(
      child: Container(
        height: 100,
        width: 100,
      ),
    );
  }
}

这是我最初编写的用于查找小部件的测试,当然失败了。

void main() {
  testWidgets('main contains mywidget', (WidgetTester tester) async {
    // arange
    await tester.pumpWidget(MyApp());
    // act
    final myWidget = find.byType(MyWidget);
    // assert
    expect(myWidget, findsOneWidget);
  });
}

在这个迭代中,我使用了 WidgetTester.scrollUntilVisible 函数,但遇到了以下错误。
void main() {
  testWidgets('main contains mywidget', (WidgetTester tester) async {
    // arange
    await tester.pumpWidget(MyApp());
    // act
    final myWidget = find.byType(MyWidget);
    final customScrollView = find.byType(CustomScrollView);
    await tester.scrollUntilVisible(myWidget, 100,
        scrollable: customScrollView);
    await tester.pump();
    // assert
    expect(myWidget, findsOneWidget);
  });
}

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following _CastError was thrown running a test:
type 'CustomScrollView' is not a subtype of type 'Scrollable' in type cast

When the exception was thrown, this was the stack:
#0      WidgetController.widget (package:flutter_test/src/controller.dart:66:44)
#1      WidgetController.scrollUntilVisible.<anonymous closure> (package:flutter_test/src/controller.dart:995:15)
#2      WidgetController.scrollUntilVisible.<anonymous closure> (package:flutter_test/src/controller.dart:993:39)
#5      TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
#6      WidgetController.scrollUntilVisible (package:flutter_test/src/controller.dart:993:27)
#7      main.<anonymous closure> (file:///C:/Users/X/test_example/test/main_test.dart:12:18)
<asynchronous suspension>
<asynchronous suspension>
(elided 3 frames from dart:async and package:stack_trace)

我很感激任何帮助或建议,以解决这个问题并成功测试我的CustomScrollView

2个回答

14

我曾经遇到同样的问题,最终我使用了dragUntilVisible() 方法,而不是scrollUntilVisible()方法。

下面是滚动直到小部件可见的示例:

await tester.dragUntilVisible(myWidget, customScrollView, Offset(0, -500));

我对其背后的逻辑很好奇。遇到了同样的问题,你救了我。 - Eng

0
只需在点击之前使用"await tester.ensureVisible(find.byKey(Key("key_of_the_element")));"。它会滚动直到给定的元素可见。这比dragUntilVisible或scrollUntilVisible更好,因为dragUntilVisible对于非渲染框小部件不起作用,而scrollUntilVisible对于非可滚动小部件不起作用。

package:flutter_test/src/controller.dart

未来 ensureVisible(Finder finder)
所属类:WidgetController 类型:Future Function(Finder)
给定一个由finder指定的小部件W和其祖先树中的可滚动小部件S,此方法将S滚动到使W可见的位置。 通常,此方法的finder应标记为skipOffstage: false,以便Finder正确处理屏幕外的小部件。 当S足够长且离显示部分的S足够远时,此方法不起作用,因为S尚未缓存W的元素。在这种情况下,考虑使用scrollUntilVisible方法。 另请参阅: Scrollable.ensureVisible,这是用于实现此方法的生产API。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接