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

Flutter:使用fake_cloud_firestore测试Firestore Repository时when()桩方法未触发的问题排查

解决FakeCloudFirestore与Mockito配合时的方法打桩问题

你遇到的Bad state: No method stub was called from within when()错误,核心原因是**FakeFirebaseFirestore不是Mockito生成的mock对象**——它是一个预实现的模拟类,专门用来模拟Firestore的真实数据操作逻辑,但无法被Mockito的when()方法拦截和打桩。

正确的解决方案:用Mockito完整mock Firestore调用链

既然你要测试异常分支,完全用Mockito来mock整个Firestore调用流程会更直接。下面是修改后的测试代码:

第一步:定义Mockito的Mock类

在测试文件中添加这些mock类,用来模拟Firestore的各个层级:

import 'package:mockito/mockito.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

class MockFirebaseFirestore extends Mock implements FirebaseFirestore {}
class MockCollectionReference extends Mock implements CollectionReference {}
class MockDocumentReference extends Mock implements DocumentReference {}

第二步:初始化测试依赖

替换原来的FakeFirebaseFirestore为Mockito的mock实例:

final mockFirestore = MockFirebaseFirestore();
final userRepository = UserRepository(mockFirestore);

第三步:修改测试代码,正确打桩异常

test('updateUser returns unexpected failure on general exception', () async {
  // 准备测试数据
  final Map<String, dynamic> jsonMap = json.decode(
    fixture("user/full_domain_fuser.json"),
  );
  final FUser fuser = FUser.fromJson(jsonMap);
  final userJson = UserDTO.fromDomainForUpdatingProfile(fuser).toJson();

  // 构建Firestore调用链的mock
  final mockCollectionRef = MockCollectionReference();
  final mockDocRef = MockDocumentReference();

  // 打桩每个层级的调用,返回对应的mock实例
  when(mockFirestore.collection(FirestoreCollections.COLLECTION_USERS))
      .thenReturn(mockCollectionRef);
  when(mockCollectionRef.doc(fuser.id)).thenReturn(mockDocRef);
  // 打桩set方法抛出异常
  when(mockDocRef.set(userJson, SetOptions(merge: true)))
      .thenThrow(Exception());

  // 执行待测试方法
  final result = await userRepository.updateUser(fuser);

  // 验证结果(注意:原来的断言写错了,要实例化具体的Failure)
  expect(result, const Left(UserFailure.unexpected()));

  // 可选:验证方法是否被正确调用过一次
  verify(mockDocRef.set(userJson, SetOptions(merge: true))).called(1);
});

额外注意事项

  1. 断言修正:你原来的expect(result, const Left(UserFailure))是错误的,UserFailure是类,需要实例化具体的失败类型(比如UserFailure.unexpected())。
  2. FakeCloudFirestore的适用场景:如果你要测试正常的更新成功流程(比如验证Firestore中的数据是否正确),fake_cloud_firestore是很好的选择;但测试异常分支时,Mockito的mock方式更灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 22:57:41