如何在小部件测试中找到离屏 ListView 子项?

Jor*_*ies 5 flutter flutter-test

在 ListView 中显示多个子项时,如果子项在屏幕外,则无法通过小部件测试找到。这是一个完整的例子:

main.dart

import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: Scaffold(body: Test()));
  }
}

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        Container(
          height: 600,
          color: Colors.red,
        ),
        Text("Find me!"),
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

main_test.dart

import 'package:flutter_app/main.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets("Find text", (WidgetTester tester) async {
    final testableWidget = App();

    await tester.pumpWidget(testableWidget);

    expect(find.text("Find me!"), findsOneWidget);
  });
}
Run Code Online (Sandbox Code Playgroud)

此测试失败,但是如果我将Containermain.dart 中的高度更改为599有效。

有谁知道为什么会这样?这是一个错误吗?有办法解决吗?

Rém*_*let 8

测试应该像您的应用程序一样运行,否则,您的测试将变得毫无用处(因为您没有测试实际行为)。因此,这不是错误。

您必须手动滚动ListView测试内部以使其加载更多小部件。

这可以使用tester

final gesture = await tester.startGesture(Offset.zero /* THe position of your listview */ );
// Manual scroll
await gesture.moveBy(const Offset(0, 100));

await tester.pump(); // flush the widget tree 
Run Code Online (Sandbox Code Playgroud)

  • 值得一提的是,您还可以拖动列表视图中的小部件:`await tester.drag(find.byType(Container), Offset(0.0, -200)); 等待 tester.pump();` (6认同)

Tou*_*der 5

在 Finder 中设置skipOffstatefalse是另一种方法。尝试这个:

expect(find.text("Find me!", skipOffstage: false), findsOneWidget);
Run Code Online (Sandbox Code Playgroud)

  • 建议编辑:我认为 *skipOffstate* 不再是 *ensureVisible* 方法的参数:https://api.flutter.dev/flutter/widgets/Scrollable/ensureVisible.html (2认同)