首页 > 解决方案 > Flutter:如何测试 Widgets State 类中的方法?

问题描述

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

class DefaultDrawerState extends State<DefaultDrawer> {

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

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

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

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

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);
  });
}

标签: unit-testingflutterwidget

解决方案


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

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

...并在测试中,直接调用 WidgetwidgetTester.pumpWidget(SampleWidget().getWidget());以将其呈现以进行测试。

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 上的一些 Widget 需要 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'),
        ),
      ),
    );
  }
}

推荐阅读