单元测试中Query<T>返回类型的正确预期方式是什么?
如何为返回Query的Firestore方法编写单元测试预期?
我们在Firebase单元测试中,针对流可以用emits(expectedData)断言返回结果,针对Future类型可以用completion(expectedData)。但当方法返回Query<T>类型时,该如何编写单元测试的预期逻辑?
测试代码示例
group('collectionQuery test', () { final service = FirestoreService(firestore: fakeService); test('expect to return the collection', () async { for (var i = 0; i < testData.length; i++) { final path = 'collections/id10$i'; await service.setData(path: path, data: testData[i].toMap()); } final Query<Post> result = service.collectionQuery( path: collectionPath, fromMap: ((snapshot, options) => Post.fromMap(snapshot.data()!, snapshot.id)), toMap: ((post, options) => post.toMap())); expect(result, // 这里该写什么断言逻辑?); }); });
被测函数实现
Query<T> collectionQuery<T>({ required String path, required T Function(DocumentSnapshot<Map<String, dynamic>> snapshot, SnapshotOptions? options) fromMap, required Map<String, Object?> Function(T, SetOptions? options) toMap, }) { Query<T> query = firestore .collection(path) .withConverter<T>(fromFirestore: fromMap, toFirestore: toMap); return query; }
解决方案
Query<T>本质是一个查询构造器,直接断言它本身意义不大,更合理的测试方向是验证查询的配置是否正确,或者执行查询后返回的数据是否符合预期,具体可以分两种方式:
1. 验证Query的基础配置
如果只需要确认collectionQuery方法正确构建了Query实例,可以检查它的集合路径(如果使用Fake Firestore库,通常能直接获取这类属性):
// 验证查询指向的集合路径是否正确 expect(result.path, collectionPath);
2. 执行Query并验证返回数据
更有实际意义的测试是执行这个Query,获取实际查询结果后和预期数据对比:
// 执行查询获取快照 final querySnapshot = await result.get(); // 将快照文档转换为Post列表 final actualPosts = querySnapshot.docs.map((doc) => doc.data()).toList(); // 断言实际结果和测试数据一致 expect(actualPosts, testData);
修改后的完整测试代码:
group('collectionQuery test', () { final service = FirestoreService(firestore: fakeService); test('expect to return the collection with correct data', () async { // 预先插入测试数据 for (var i = 0; i < testData.length; i++) { final path = 'collections/id10$i'; await service.setData(path: path, data: testData[i].toMap()); } // 获取构造好的Query final Query<Post> result = service.collectionQuery( path: collectionPath, fromMap: ((snapshot, options) => Post.fromMap(snapshot.data()!, snapshot.id)), toMap: ((post, options) => post.toMap())); // 执行查询并验证结果 final querySnapshot = await result.get(); final actualPosts = querySnapshot.docs.map((doc) => doc.data()).toList(); expect(actualPosts, testData); // 额外验证查询路径是否正确 expect(result.path, collectionPath); }); });
注意:要让
expect(actualPosts, testData)生效,需要确保Post类重写了==运算符和hashCode方法,否则会默认比较对象引用,导致断言失败。
内容的提问来源于stack exchange,提问作者john
相关产品推荐
相关产品推荐

