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

单元测试中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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 08:55:17