Mocha+Chai如何验证函数返回对象是输入参数的克隆
问题排查与正确写法指引
第一步:先修复基础代码的低级错误
你写的clone.js首先存在导出逻辑错误:
// 你当前的代码 function makeClone (objectToClone) { return Object.assign({}, objectToClone) } module.exports = clone // 这里引用了不存在的变量clone,运行时直接报ReferenceError
修正为和定义的函数名匹配的导出逻辑:
function makeClone (objectToClone) { return Object.assign({}, objectToClone) } module.exports = makeClone
第二步:理清Chai expect断言的基本规则
你之前写的两处断言错误,本质是三个常见的新手误区:
- 括号位置错误:
expect(clone({a:1, b:2}).to.equal({a:1, b:2}))把.to.equal写到了expect的括号内部,相当于把方法调用绑定在了clone()函数的返回值上,完全跳过了Chai的断言对象,根本不会触发校验。正确结构是把待断言值作为expect的入参,再在外层链式拼接断言方法:expect(clone({a:1, b:2})).to.equal({a:1, b:2}) - 断言方法选择错误:哪怕括号位置写对,用
.equal也永远通不过。因为Chai的.equal对应JS的严格相等判定(===),只校验两个值的内存引用是否完全一致——你用Object.assign生成的是全新对象,哪怕属性内容和原对象100%匹配,内存地址也不同,用equal判定必然失败。 - 链式修饰词误用:你写的
expect(clone({a: 1, b: 2})).to.be.equal.to({a: 1, b: 2})里,最后一个.to是无实际校验作用的语义修饰词,不是断言方法,写完之后等于没有执行任何值对比动作,测试相当于空跑。
新手记断言链逻辑不用死磕文档:
expect(待校验值).[无逻辑作用的语义修饰词(to、be、been、is都可以随便加)].[真正的断言方法(期望值)],修饰词只用来让语句读着通顺,不改变校验逻辑。
第三步:验证浅克隆的完整测试用例
你要验证「函数返回的是对象的克隆」,其实需要两个维度的校验:
- 克隆出来的对象,第一层属性值和原对象完全一致
- 克隆出来的对象,和原对象不是同一个内存引用(避免函数偷懒直接返回原对象,根本没做克隆动作)
对应用到的Chai断言:
- 校验属性值一致:用
.eql,它会递归对比对象的所有可枚举属性值,不要求内存地址相同 - 校验引用不同:用
.equal搭配.not,专门用来对比内存引用是否一致
可直接运行的testClone.js代码
const expect = require('chai').expect const makeClone = require('./clone.js') describe('浅克隆函数', function () { it('返回对象的属性与传入对象完全匹配', function () { const sourceObj = {a: 1, b: 2} const clonedObj = makeClone(sourceObj) expect(clonedObj).to.eql(sourceObj) }) it('返回的克隆对象与原对象不是同一内存引用', function () { const sourceObj = {a: 1, b: 2} const clonedObj = makeClone(sourceObj) expect(clonedObj).to.not.equal(sourceObj) }) })
内容的提问来源于stack exchange,提问作者Zepstack
相关产品推荐
相关产品推荐

