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

Flutter测试中如何Mock SharedPreferences.getInstance()?

Flutter测试中正确Mock SharedPreferences.getInstance()的方法

问题根源

你当前的测试代码无效,核心问题有两个:

  • SharedPreferences.getInstance()是静态方法,你Mock的是自定义MockSharedPreferences类的静态方法,但实际登录逻辑调用的是SharedPreferences原生类的getInstance(),两者不匹配。
  • 常规mocktail的实例Mock方式不适用于静态方法,必须通过SharedPreferences提供的初始化入口替换实现。

推荐方案:使用shared_preferences_test包

这是官方维护的测试工具,专门处理SharedPreferences的Mock,步骤如下:

  1. 在pubspec.yaml的dev_dependencies中添加依赖:
dev_dependencies:
  shared_preferences_test: ^2.2.0 # 请使用最新版本
  1. 修改测试代码:
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:shared_preferences_test/shared_preferences_test.dart';
import 'package:mocktail/mocktail.dart';

class MockSharedPreferences extends Mock implements SharedPreferences {}

void main() {
  group('Login Tests', () {
    testWidgets('Login success saves token to SharedPreferences', (WidgetTester tester) async {
      // 创建Mock实例
      final mockPrefs = MockSharedPreferences();
      
      // 替换SharedPreferences.getInstance的返回值
      when(() => SharedPreferences.getInstance()).thenAnswer((_) async => mockPrefs);

      // 需先Mock Dio的post请求(避免真实网络调用),再触发登录操作
      // ... 你的登录触发逻辑 ...

      // 验证是否正确调用setString保存token
      verify(() => mockPrefs.setString('token', any())).called(1);
    });
  });
}

备选方案:手动覆盖静态方法

如果不想添加额外依赖,可直接覆盖SharedPreferences.getInstance的实现:

import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:mocktail/mocktail.dart';

class MockSharedPreferences extends Mock implements SharedPreferences {}

void main() {
  late MockSharedPreferences mockPrefs;
  // 保存原getInstance方法,测试后恢复
  late Future<SharedPreferences> Function() originalGetInstance;

  setUp(() {
    mockPrefs = MockSharedPreferences();
    originalGetInstance = SharedPreferences.getInstance;
    // 替换为Mock实例
    SharedPreferences.getInstance = () async => mockPrefs;
  });

  tearDown(() {
    // 恢复原方法,避免影响其他测试
    SharedPreferences.getInstance = originalGetInstance;
  });

  testWidgets('Login success saves token', (WidgetTester tester) async {
    // 触发登录操作
    // ...

    // 验证token保存逻辑
    verify(() => mockPrefs.setString('token', 'test_token')).called(1);
  });
}

额外提醒

  • 登录代码中的Dio网络请求必须Mock,否则测试会卡在网络调用环节或失败。
  • 对于Bloc和Navigator的操作,测试时需确保Widget树包含对应的BlocProvider,或用NavigatorObserver验证导航行为,避免相关逻辑出错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:33:34