应优先使用structuredclone()实现测试数据深拷贝,它支持现代环境并正确处理date、regexp、map等类型及循环引用;旧环境或复杂数据用_.clonedeep();手写递归用于精准控制;禁用json.parse(json.stringify())。

在自动化测试脚本中,为每个测试用例提供独立的数据环境,核心是确保测试间零干扰——改了副本,绝不影响原始测试数据或其它用例的副本。深拷贝就是实现这层隔离的关键操作,但选错方法会导致隐性失败:比如日期变字符串、正则失效、循环引用报错,甚至不同用例意外共享了同一个 Map 实例。
优先用 structuredClone() 处理多数现代测试环境
Chrome 98+、Firefox 94+、Safari 15.4+ 和 Node.js 18.15+/20.6+ 均稳定支持 structuredClone(),它能正确复制 Date、RegExp、Map、Set、ArrayBuffer 等常见测试数据类型,且自动处理循环引用,无需额外逻辑:
- 测试前直接调用
const testData = structuredClone(originalFixture); - 适合含时间戳、配置对象、模拟响应体(如 API 返回的嵌套 JSON + Date 字段)等典型测试数据
- 注意避开函数、Symbol、undefined —— 测试数据本身通常不含这些,若需存桩函数,应单独注入而非深拷贝
用 Lodash 的 _.cloneDeep() 应对复杂数据和旧环境兼容
当测试需运行在 Node.js 16 或旧版浏览器(如 Electron 旧内核),或数据中混有不可枚举属性、自定义类实例、getter/setter 时,_.cloneDeep() 更稳妥:
- 它能保留原型链信息(对继承自特定基类的 mock 对象有用)
- 支持 Symbol 作为 key(如某些库用 Symbol 存元数据)
- 对函数默认跳过(符合测试数据惯例),也可通过定制化 replacer 处理特殊逻辑
- 安装轻量:仅需
npm install lodash.clonedeep,按需引入避免打包体积膨胀
手写递归深拷贝用于精准控制与调试
当需要明确知道哪些字段被忽略、哪些类型被转换(例如统一将 Date 转为固定字符串便于快照比对),或排查深拷贝异常时,可封装一个最小可用版本:
- 用 WeakMap 缓存已遍历对象,彻底防止循环引用栈溢出
- 显式处理 Date、RegExp、Map、Set:分别用
new Date()、new RegExp()、new Map([...map])等重建 - 跳过函数和 undefined(测试数据中极少需要拷贝函数)
- 不复制原型和不可枚举属性——这对测试隔离是优点,避免污染 mock 行为
避免 JSON.parse(JSON.stringify()) 在测试中使用
尽管写法简洁,但它在测试场景下风险集中:
- Date 变成 ISO 字符串,后续
testData.date.getTime()报错 - Map/Set 变成空对象
{},断言testData.map.size崩溃 - NaN 变成 null,Infinity 变成 null,导致数值断言静默失败
- 循环引用直接中断整个测试套件(如 mock 的响应对象里引用了 request 对象)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











