一尘不染

如何在Flutter中通过Navigator测试导航

flutter

假设,我使用来测试Flutter中的屏幕WidgetTester。有一个按钮,可通过进行导航Navigator。我想测试该按钮的行为。

小部件/屏幕

class MyScreen extends StatefulWidget {

  MyScreen({Key key}) : super(key: key);

  @override
  _MyScreenState createState() => _MyScreenScreenState();
}

class _MyScreenState extends State<MyScreen> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child: RaisedButton(
                onPressed: () {
                    Navigator.of(context).pushNamed("/nextscreen");
                },
                child: Text(Strings.traktTvUrl)
            )
        )
    );
  }

}

测试

void main() {

  testWidgets('Button is present and triggers navigation after tapped',
      (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(home: MyScreen()));
    expect(find.byType(RaisedButton), findsOneWidget);
    await tester.tap(find.byType(RaisedButton));
    //how to test navigator?    
  });
}

我有一个正确的方法如何检查Navigator是否被调用?还是有一种方法可以模拟和替换导航器?

请注意,上面的代码实际上会因一个异常而失败,因为'/nextscreen'在应用程序中没有声明命名的路由。解决起来很简单,您无需指出。

我主要关心的是如何在Flutter中正确处理此测试方案。


阅读 263

收藏
2020-08-13

共1个答案

一尘不染

flutter仓库中导航器测试中,他们使用NavigatorObserver类观察导航:

class TestObserver extends NavigatorObserver {
  OnObservation onPushed;
  OnObservation onPopped;
  OnObservation onRemoved;
  OnObservation onReplaced;

  @override
  void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
    if (onPushed != null) {
      onPushed(route, previousRoute);
    }
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
    if (onPopped != null) {
      onPopped(route, previousRoute);
    }
  }

  @override
  void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) {
    if (onRemoved != null)
      onRemoved(route, previousRoute);
  }

  @override
  void didReplace({ Route<dynamic> oldRoute, Route<dynamic> newRoute }) {
    if (onReplaced != null)
      onReplaced(newRoute, oldRoute);
  }
}

看起来它应该可以满足您的要求,但是它只能在顶层(MaterialApp)上运行,我不确定是否可以仅将其提供给小部件。

2020-08-13