You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单元测试中Mock Navigator.of(context).pushNamed()的返回值?

如何Mock Navigator.pushNamed返回值测试全局变量更新

你需要用mockito库Mock Navigator的pushNamed方法,指定其返回true或false,再验证全局变量的状态变化。以下是完整实现步骤和代码示例:

1. 依赖准备

确保你的pubspec.yaml包含测试所需依赖:

dev_dependencies:
  flutter_test:
    sdk: flutter
  mockito: ^5.4.0

2. 示例全局变量与目标函数

假设你有如下全局状态类和需要测试的导航处理函数:

// 全局状态类
class GlobalState {
  static bool isGlobalUpdated = false;

  static void updateGlobal() {
    isGlobalUpdated = true;
  }

  static void reset() {
    isGlobalUpdated = false;
  }
}

// 需要测试的导航处理函数
Future<void> handleNavigation(BuildContext context) async {
  final isUpdated = await Navigator.of(context).pushNamed('/targetRoute');
  
  if (isUpdated == true) {
    GlobalState.updateGlobal();
  }
}

3. 编写单元测试

通过testWidgets创建两个测试用例,分别Mock返回true和false的场景:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';

// Mock NavigatorObserver,避免真实导航操作
class MockNavigatorObserver extends Mock implements NavigatorObserver {}

void main() {
  // 每次测试前重置全局变量,保证测试独立性
  setUp(() {
    GlobalState.reset();
  });

  testWidgets('pushNamed返回true时,全局变量应被更新', (tester) async {
    // 构建包含目标按钮的MaterialApp,注入Mock导航观察者
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Builder(
            builder: (context) {
              return ElevatedButton(
                onPressed: () => handleNavigation(context),
                child: const Text('Test'),
              );
            },
          ),
        ),
        navigatorObservers: [MockNavigatorObserver()],
      ),
    );

    // 获取有效BuildContext
    final context = tester.element(find.byType(ElevatedButton));

    // Mock pushNamed方法,指定返回true
    when(Navigator.of(context).pushNamed('/targetRoute')).thenAnswer((_) async => true);

    // 执行目标函数
    await handleNavigation(context);

    // 断言全局变量状态
    expect(GlobalState.isGlobalUpdated, isTrue);
  });

  testWidgets('pushNamed返回false时,全局变量不应被更新', (tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Builder(
            builder: (context) {
              return ElevatedButton(
                onPressed: () => handleNavigation(context),
                child: const Text('Test'),
              );
            },
          ),
        ),
        navigatorObservers: [MockNavigatorObserver()],
      ),
    );

    final context = tester.element(find.byType(ElevatedButton));

    // Mock pushNamed方法,指定返回false
    when(Navigator.of(context).pushNamed('/targetRoute')).thenAnswer((_) async => false);

    await handleNavigation(context);

    // 断言全局变量状态
    expect(GlobalState.isGlobalUpdated, isFalse);
  });
}

核心说明

  • 使用mockito的when方法直接MockNavigator.of(context).pushNamed的返回值,无需关注真实导航流程
  • 每次测试前通过setUp重置全局变量,确保单个测试用例的独立性
  • 通过testWidgets构建Widget树获取有效的BuildContext,因为Navigator必须依附于可用上下文

内容的提问来源于stack exchange,提问作者countpablo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 02:12:04