深拷贝是保障toStrictEqual断言可靠性的关键前置操作,用于避免嵌套引用或可变状态导致的状态污染;需配合structuredClone、lodash.cloneDeep等实现值隔离,但不解决语义等价问题。

深拷贝本身不直接参与 toStrictEqual 断言,但它是保障断言可靠性的关键前置操作——尤其当测试对象含嵌套引用或可变状态时。
为什么需要先深拷贝再用 toStrictEqual
toStrictEqual(如 Jest 中)或 assert.deepStrictEqual(Node.js 原生)做的是“深度严格相等”校验:不仅比值,还要求类型一致、引用结构一致。但如果待测对象被意外修改过,或多个测试共享同一数据源,原始值可能已变,导致断言失败不是因为逻辑错,而是因为状态污染。
常见场景包括:
- 测试中复用一个全局配置对象,后续测试改了它的某个字段
- 接口响应解析后直接赋给多个断言变量,而其中某次操作修改了内部数组或子对象
- 使用 mock 返回的响应体被测试函数内部 mutate(比如 push 到数组、赋新属性)
典型做法:深拷贝 + toStrictEqual
以 Jest 为例,推荐在准备期望值或实际值时显式深拷贝:
- 用
JSON.parse(JSON.stringify(obj))快速克隆简单对象(不含函数、undefined、Date、RegExp 等) - 用
structuredClone(obj)(Node.js 17.6+ / 浏览器支持)处理更复杂类型 - 用
lodash.cloneDeep(obj)应对全量 JS 类型(需引入依赖)
示例:
const original = { user: { id: 1, profile: { name: 'Alice' } }, tags: ['a', 'b'] };
const expected = structuredClone(original); // ✅ 防止后续修改影响
// 模拟被测函数返回值
const actual = service.getUser();
// 断言前确保两者都是独立副本
expect(actual).toStrictEqual(expected); // ✅ 类型+结构+值全匹配
对比浅比对(如 toEqual / equal)的风险
toEqual 或 assert.equal 默认只做浅比较或宽松相等(如 1 == '1'),容易掩盖问题:
- 它不会报出
Date对象类型不一致(new Date() !== new Date(),但toEqual可能通过) - 对
NaN、undefined、Symbol处理不一致 - 若对象内部有循环引用,
toEqual可能静默失败或抛错,而toStrictEqual明确拒绝循环引用
所以,当你要验证“完全一致”的契约(比如 API 响应结构、序列化结果、Redux state 快照),必须搭配深拷贝 + toStrictEqual 才能真正锁定行为。
注意边界:深拷贝不是万能解药
深拷贝解决的是“值隔离”,不是“语义等价”。例如:
- 两个
class实例即使字段全同,toStrictEqual仍会失败(除非它们是同一构造函数且原型链一致) - 函数、正则、Map/Set 等需特殊处理,
structuredClone不支持 Map/Set 的键值对复制(部分环境),此时需手动重建或改用expect.objectContaining局部校验 - 过度深拷贝影响性能,高频测试中建议只对必要字段克隆,或用不可变数据结构(如 Immutable.js、Immer)替代

















