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

Flutter单元测试中如何使用Mockito模拟Firebase Crashlytics?

Flutter单元测试模拟Firebase Crashlytics实现方案

问题场景

接入Firebase Crashlytics后,对下述异常处理逻辑编写单元测试时:

if (queryResult.hasException) {
  String msg = queryResult.exception.toString();
  await FirebaseCrashlytics.instance.recordError(error, stackTrace, reason: message, fatal: true);
  throw Exception("Query execution failed due to: " + msg);
}

如果不对Firebase实例做模拟,测试运行时会直接抛出报错:

No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()

需要在测试中模拟Firebase实例,拦截真实的错误记录操作,既避免初始化报错,也防止测试数据上报到线上Crashlytics后台。

具体实现

  • 先添加测试需要的依赖
    在pubspec.yaml的dev_dependencies节点下加入以下依赖:
    dev_dependencies:
      flutter_test:
        sdk: flutter
      mockito: ^5.4.0
      build_runner: ^2.4.0
      firebase_core_platform_interface: ^4.8.0
      firebase_crashlytics_platform_interface: ^3.6.0
    
  • 测试初始化阶段注入Mock实例,跳过真实SDK初始化
    不需要在测试里真的调用Firebase.initializeApp()连接线上服务,直接利用Firebase提供的测试桩替换底层平台实现即可:
    import 'package:firebase_core/firebase_core.dart';
    import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart';
    import 'package:firebase_crashlytics/firebase_crashlytics.dart';
    import 'package:firebase_crashlytics_platform_interface/firebase_crashlytics_platform_interface.dart';
    import 'package:flutter_test/flutter_test.dart';
    import 'package:mockito/mockito.dart';
    
    class MockCrashlyticsPlatform extends Mock implements FirebaseCrashlyticsPlatform {}
    
    void main() {
      late MockCrashlyticsPlatform mockPlatform;
    
      setUpAll(() async {
        TestWidgetsFlutterBinding.ensureInitialized();
        // 注入Firebase Core测试桩,绕过DEFAULT应用初始化校验
        setupFirebaseCoreMocks();
        // 生成测试用的空Firebase实例,不会发起真实网络请求
        await Firebase.initializeApp();
    
        // 替换Crashlytics底层平台实例为Mock对象
        mockPlatform = MockCrashlyticsPlatform();
        FirebaseCrashlyticsPlatform.instance = mockPlatform;
        // 给recordError设置默认空返回,避免调用时抛未实现异常
        when(mockPlatform.recordError(any, any, any)).thenAnswer((_) async {});
      });
    
  • 编写测试用例验证逻辑
    测试过程中既可以校验异常是否正常抛出,也可以验证Crashlytics的上报逻辑是否按预期触发,全程不会产生真实上报:
    test('查询出现异常时会调用Crashlytics记录错误并抛出包装后的异常', () async {
        // 构造带异常的测试查询结果
        final testQueryResult = QueryResult(
          hasException: true,
          exception: OperationException(),
          source: null,
        );
    
        // 验证方法确实抛出了预期异常
        expect(
          () => runYourQueryLogic(testQueryResult),
          throwsA(isA<Exception>().having(
            (e) => e.toString(),
            '异常信息',
            contains('Query execution failed due to'),
          )),
        );
    
        // 验证Crashlytics的recordError确实被调用了1次
        verify(mockPlatform.recordError(any, any, any)).called(1);
      });
    }
    

注意事项

  • 不要在单元测试中真实初始化线上Firebase应用,否则测试过程中产生的错误记录会上传到线上Crashlytics后台,污染真实的崩溃数据。
  • 如果觉得手写Mock类麻烦,可以给FirebaseCrashlyticsPlatform添加@GenerateMocks注解,通过build_runner命令自动生成Mock代码,减少手动编码工作量。
  • 业务代码中原有的FirebaseCrashlytics.instance调用不需要做任何修改,Firebase SDK本身做了平台层解耦,替换底层平台实例后,上层所有调用都会自动路由到Mock对象上,不会触发真实的上报逻辑。

内容的提问来源于stack exchange,提问作者Răzvan Puiu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:24:28