【问题标题】:Flutter: How to test a method inside a Widgets State class?Flutter:如何测试 Widgets State 类中的方法?
【发布时间】:2019-09-16 05:50:41
【问题描述】:

我有一个小部件测试,用于我命名为DefaultDrawer 的抽屉。我也想测试一下我在DefaultDrawerState.里面做的方法比如,

class DefaultDrawerState extends State<DefaultDrawer> {

  @override
  Widget build(BuildContext context) {
    // ..build..
  }

  Widget _circleAvatar() {
    // a method I want to test
  }
}

flutter_test 查找器似乎无法调用我的小部件或其状态中的方法时,我如何测试方法_circleAvatar()

下面是我现在的测试文件,没有测试小部件内部的方法:

void main() {
  testWidgets('Drawer Test', (WidgetTester tester) async {
    final key = GlobalKey<ScaffoldState>();
    await tester.pumpWidget(
        MaterialApp(home: Scaffold(key: key, drawer: DefaultDrawer())));

    // open drawer
    key.currentState.openDrawer();
    await tester.pump();

    // did drawer open?
    final drawerFinder = find.byType(Drawer);
    expect(drawerFinder, findsOneWidget);
  });
}

【问题讨论】:

  • 测试小部件的方法被认为是不好的做法。这些是实现细节。
  • 那么最佳实践是什么?
  • 由于您的_circleAvatar 将在您的build 方法中被调用,因此只需使用find 检查一切都已就位。
  • @remi 但是将“内部”小部件分离到它们自己的无状态小部件类可能会提供可单元测试的方式?喜欢 => flutter.institute/flutter-and-widget-tests
  • @ahaaman 避免以通常不使用的方式测试小部件。

标签: unit-testing flutter widget


【解决方案1】:

为了能够测试 Widget,您需要使用 WidgetTester.pumpWidget(Widget) 在集成测试中呈现 UI。让`SampleWidget

class SampleWidget {
  Widget getWidget() {
    return Container(
      key: Key('SampleWidget'),
      color: Colors.green,
    );
  }
}

...在测试中,直接用widgetTester.pumpWidget(SampleWidget().getWidget());调用Widget来渲染它进行测试。

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();
  
  testWidgets("Test Widget", (WidgetTester widgetTester) async {
    bool found = false;
    await widgetTester.pumpWidget(SampleWidget().getWidget());
    widgetTester.allWidgets.forEach((Widget element) {
      if(element.key.toString().contains('SampleWidget')){
        debugPrint('Found Sample Widget!');
        found = true;
      }
    });
    expect(found, true);
  });
}

测试应该能够找到包含指定键的小部件元素。

但是,WidgetTester 上的一些小部件需要 MaterialApp 作为其父级。这个小部件的一个例子是文本 - 它需要方向性,方向性可以通过使用 MaterialApp 或 WidgetsApp 小部件找到。在测试中渲染没有 MaterialApp 的 Text Widget 将失败。将抛出此错误。

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞════════════════════════
The following assertion was thrown building Text("Demo Widget"):
No Directionality widget found.
RichText widgets require a Directionality widget ancestor.
The specific widget that could not find a Directionality ancestor
was:
  RichText
The ownership chain for the affected widget is: "RichText ← Text
  ← Center ← ColoredBox ← Container-[<'SampleWidget'>] ←
  RepaintBoundary ← [root]"
Typically, the Directionality widget is introduced by the
MaterialApp or WidgetsApp widget at the top of your application
widget tree. It determines the ambient reading direction and is
used, for example, to determine how to lay out text, how to
interpret "start" and "end" values, and to resolve
EdgeInsetsDirectional, AlignmentDirectional, and other
*Directional objects.

作为此用例的解决方法,您可以使用 MaterialApp 包装您的小部件。

class SampleWidget{
  Widget getWidget() {
    return MaterialApp(
      home: Container(
        key: Key('SampleWidget'),
        color: Colors.green,
        child: Center(
          child: Text('Demo Widget'),
        ),
      ),
    );
  }
}

【讨论】:

    猜你喜欢
    • 2020-12-12
    • 2020-02-28
    • 2022-06-19
    • 1970-01-01
    • 2020-02-05
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    相关资源
    最近更新 更多