首页 > 解决方案 > Flutter pushReplacementNamed 未通过测试

问题描述

我有两个屏幕(登录和注册),它们的按钮分别相互链接。对于登录页面,一个按钮触发pushReplacementNamed导航到注册页面。同样,在注册页面中,一个不同的按钮触发pushReplacementNamed导航到登录页面。

login_screen.dart:

SecondaryButton(
  onPressed: () {
    Navigator.pushReplacementNamed(context, SignupScreen.id);
  },
  key: LoginScreen.signupBtnKey,
  child: Text('Sign Up'),
),

signup_screen.dart:

SecondaryButton(
  onPressed: () {
    Navigator.pushReplacementNamed(context, LoginScreen.id);
  },
  key: SignupScreen.loginBtnKey,
  child: Text('Log In'),
)

在模拟器上进行测试时,两个按钮似乎都可以正常工作,但在尝试运行自动化测试时,它不适用于注册屏幕。

login_screen_test.dart

class MockNavigatorObserver extends Mock implements NavigatorObserver {}

void main() {

  group('Login Screen Widget Tests', () {

    NavigatorObserver mockObserver;

    setUp(() {
      mockObserver = MockNavigatorObserver();
    });

    Widget createLoginScreen() {
      return MaterialApp(
        initialRoute: LoginScreen.id,
        routes: {
          LoginScreen.id: (context) => LoginScreen(),
          SignupScreen.id: (context) => SignupScreen(),
        },
        navigatorObservers: [mockObserver],
      );
    }

    testWidgets(
      'Testing if sign up button shows up and triggers navigation after tapped',
      (tester) async {
        await tester.pumpWidget(createLoginScreen());
        expect(find.byKey(LoginScreen.signupBtnKey), findsOneWidget);
        await tester.tap(find.byKey(LoginScreen.signupBtnKey));
        await tester.pumpAndSettle();
        verify(
          mockObserver.didReplace(
            oldRoute: anyNamed('oldRoute'),
            newRoute: anyNamed('newRoute'),
          ),
        );
        expect(find.byType(SignupScreen), findsOneWidget);
        expect(find.byType(LoginScreen), findsNothing);
      },
    );
  });
}

signup_screen_test.dart

class MockNavigatorObserver extends Mock implements NavigatorObserver {}

void main() {

  group('Signup Screen Widget Tests', () {

    NavigatorObserver mockObserver;

    setUp(() {
      mockObserver = MockNavigatorObserver();
    });

    Widget createSignupScreen() {
      return MaterialApp(
        initialRoute: SignupScreen.id,
        routes: {
          LoginScreen.id: (context) => LoginScreen(),
          SignupScreen.id: (context) => SignupScreen(),
        },
        navigatorObservers: [mockObserver],
      );
    }

    testWidgets(
      'Testing if log in button shows up and triggers navigation after tapped',
      (tester) async {
        await tester.pumpWidget(createSignupScreen());
        expect(find.byKey(SignupScreen.loginBtnKey), findsOneWidget);
        await tester.tap(find.byKey(SignupScreen.loginBtnKey));
        await tester.pumpAndSettle();
        verify(
          mockObserver.didReplace(
            oldRoute: anyNamed('oldRoute'),
            newRoute: anyNamed('newRoute'),
          ),
        );
        expect(find.byType(LoginScreen), findsOneWidget);
        expect(find.byType(SignupScreen), findsNothing);
      },
    );
  });
}

这失败了,但有以下例外:

The following TestFailure object was thrown running a test:
  No matching calls. All calls: MockNavigatorObserver.navigator,
MockNavigatorObserver._navigator==NavigatorState#03a3a(tickers: tracking 1 ticker),
MockNavigatorObserver.didPush(MaterialPageRoute<dynamic>(RouteSettings("/signup", null), animation:
AnimationController#9b7dc(⏭ 1.000; paused; for MaterialPageRoute<dynamic>(/signup))), null)

这表明没有触发 didReplace() 方法。每一页上的代码几乎相同,所以我不明白为什么一个会通过,而另一个会失败。

将不胜感激任何见解,可能是显而易见的!

标签: flutterdarttestingreplacenavigator

解决方案


页面前面的附加文本字段将其撞出屏幕。需要添加一个tester.fling().


推荐阅读