Flutter中cloud_firestore get函数单元测试编写问题求助
解决Firestore昵称查重单元测试失败问题
问题根源
你的MockFirebaseFirestore继承自Fake但未实现collection方法,调用时触发UnimplementedError。同时你错误混用了fake_cloud_firestore的模拟实例和mocktail的Stub逻辑——FakeFirebaseFirestore本身已经完整实现了Firestore接口,无需额外Stub。
正确实现步骤
1. 移除无用的Mock类
删除自定义的MockFirebaseFirestore类,直接使用fake_cloud_firestore提供的FakeFirebaseFirestore。
2. 修改测试初始化逻辑
在setUpAll或setUp中直接初始化FakeFirebaseFirestore,并注入到AuthRepositoryImpl:
void main() { late FakeFirebaseFirestore cloudFirestore; late AuthRepositoryImpl repositoryImpl; setUpAll(() { cloudFirestore = FakeFirebaseFirestore(); // 替换为你已实现的FirebaseAuth模拟实例 repositoryImpl = AuthRepositoryImpl( firebaseAuth: MockFirebaseAuth(), firestore: cloudFirestore, ); }); // 测试用例... }
3. 重写测试用例
直接操作FakeFirebaseFirestore中的数据,无需使用when Stub:
test('checkNickname should return Left if nickname is busy', () async { // 1. 在Fake Firestore中添加已存在的昵称数据 await cloudFirestore.collection(FirebaseCollection.users.name) .doc('test') .set({'nickname': 'nickname'}); // 2. 调用待测试方法 final result = await repositoryImpl.checkNickname(nickname: 'nickname'); // 3. 断言结果 expect(result, const Left(nicknameBusy)); }); test('checkNickname should return Right if nickname is available', () async { // 直接调用方法(Firestore中无目标昵称数据) final result = await repositoryImpl.checkNickname(nickname: 'new_nickname'); expect(result, const Right(unit)); });
4. 业务代码优化建议(可选)
当前遍历整个用户集合的方式效率较低,可改用Firestore查询直接过滤昵称,减少数据传输和遍历开销:
@override Future<Either<String, Unit>> checkNickname({required String nickname}) async { try { final querySnapshot = await firestore.collection(FirebaseCollection.users.name) .where('nickname', isEqualTo: nickname) .get(); if (querySnapshot.docs.isNotEmpty) { throw BusyNickname(); } return const Right(unit); } on BusyNickname catch (_) { return const Left(nicknameBusy); } }
内容的提问来源于stack exchange,提问作者Dawid Długosz
相关产品推荐
相关产品推荐

