How to test navigation via Navigator in Flutter


Let’s say, I have a test for a screen in Flutter using WidgetTester. There is a button, which executes a navigation via Navigator. I would like to test behavior of that button.


class MyScreen extends StatefulWidget {

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

  _MyScreenState createState() => _MyScreenScreenState();

class _MyScreenState extends State<MyScreen> {

  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child: RaisedButton(
                onPressed: () {
                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?    

I there a proper way how to check, that Navigator was called? Or is there a way to mock and replace navigator?

Pleas note, that code above will actually fail with an exception, because there is no named route '/nextscreen' declared in application. That’s simple to solve and you don’t need to point it out.

My main concern is how to correctly approach this test scenario in Flutter.


In the navigator tests in the flutter repo they use the NavigatorObserver class to observe navigations:

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

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

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

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

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

This looks like it should do what you want, however it may only work form the top level (MaterialApp), I’m not sure if you can provide it to just a widget.

Answered By – Danny Tuppeny

Answer Checked By – Katrina (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *