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

Flutter单元测试中如何校验Map数组并实现指定JSON返回逻辑

Flutter单元测试中Map数组空态测试数据统一生成实现

核心逻辑

针对单元测试中需要快速构造边界空态JSON/Map参数的需求,通过递归遍历的方式处理任意层级的Map、List(含Map数组)结构,保留原数据层级关系的同时,自动为所有叶子字段赋值null或空字符串,无需逐字段手动构造测试用例。
支持两种常用空态模式:

  • 全字段强制返回null
  • 字符串类型字段返回空字符串'',其余类型字段返回null

自动兼容嵌套Map、数组嵌套Map、基础类型数组等常见JSON结构,处理过程不会修改原始入参对象,避免测试用例之间的数据污染。

实现代码

// 空值生成模式枚举
enum EmptyTestType {
  forceNull, // 所有叶子字段返回null
  emptyStringForString, // 字符串类型叶子字段返回空字符串,其余返回null
}

/// 统一空态测试数据生成函数
/// [originalPayload] 原始正常结构的业务参数,支持Map、List、基础类型任意入参
/// [emptyType] 空值生成模式,默认为全字段返回null
dynamic generateEmptyTestPayload(
  dynamic originalPayload, {
  EmptyTestType emptyType = EmptyTestType.forceNull,
}) {
  // 处理Map结构节点
  if (originalPayload is Map<String, dynamic>) {
    final Map<String, dynamic> processedMap = {};
    originalPayload.forEach((key, value) {
      // 嵌套结构递归处理
      if (value is Map || value is List) {
        processedMap[key] = generateEmptyTestPayload(value, emptyType: emptyType);
      } else {
        // 叶子节点按规则赋值空态
        if (emptyType == EmptyTestType.emptyStringForString && value is String) {
          processedMap[key] = '';
        } else {
          processedMap[key] = null;
        }
      }
    });
    return processedMap;
  }

  // 处理List/数组结构节点(覆盖Map数组场景)
  if (originalPayload is List) {
    // 保留原数组长度,逐元素递归处理,贴合真实接口返回结构
    return originalPayload
        .map((item) => generateEmptyTestPayload(item, emptyType: emptyType))
        .toList();
  }

  // 基础类型叶子节点兜底处理
  if (emptyType == EmptyTestType.emptyStringForString && originalPayload is String) {
    return '';
  }
  return null;
}

单元测试使用示例

void main() {
  test('Map数组入参空态兼容性测试', () {
    // 原始业务正常入参样例(Map数组类型)
    final List<Map<String, dynamic>> normalUserListPayload = [
      {
        "userId": 1001,
        "userName": "zhangsan",
        "isVip": true,
        "profile": {
          "avatar": "avatar_path",
          "bio": "test intro"
        },
        "tagList": ["flutter", "unit_test"]
      }
    ];

    // 生成全字段为null的测试数据
    final nullFieldPayload = generateEmptyTestPayload(normalUserListPayload);
    // 生成字符串字段为空、其余字段为null的测试数据
    final emptyStringPayload = generateEmptyTestPayload(
      normalUserListPayload,
      emptyType: EmptyTestType.emptyStringForString,
    );

    // 直接传入待测试的业务方法/JSON解析方法即可
    expect(() => parseUserListFromJson(nullFieldPayload), returnsNormally);
    expect(() => parseUserListFromJson(emptyStringPayload), returnsNormally);
  });
}

扩展说明

  • 如果需要测试数组本身为空的场景,直接传入[]作为原始入参即可,该函数主要解决字段级空态的自动生成问题
  • 若业务需要其他类型的默认空值(比如数字类型返回0、布尔类型返回false),直接在叶子节点的判断分支中扩展对应类型的返回规则即可
  • 函数返回的是全新生成的数据实例,和原始入参完全隔离,不会修改原始测试数据影响其他用例执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:36:43