JavaScript 数组克隆相等断言中的奇怪行为
Estrange behaviour in JavaScript array clone equality assertion
我在 JavaScript 单元测试中发现了一个我想要修复的失败断言。单元测试代码如下(完整代码可见here):
beforeEach(function() {
arrNeedle = ['waffles'];
objNeedle = {w: 'waffles'};
strNeedle = 'waffles';
numNeedle = 3.14159
arrDupe = JSON.parse(JSON.stringify(arrNeedle));
objDupe = JSON.parse(JSON.stringify(objNeedle));
strDupe = JSON.parse(JSON.stringify(strNeedle));
numDupe = JSON.parse(JSON.stringify(numNeedle));
arrContainer = [arrDupe, objDupe, strDupe, numDupe];
objContainer = {
arr: arrDupe
, obj: objDupe
, str: strDupe
, num: numDupe
};
arrMissing = ['chan'];
objMissing = {missing: 'chan'}
strMissing = 'chan';
});
it("has its test set up correctly", function() {
arrNeedle.should.not.equal(arrDupe);
objNeedle.should.not.equal(objDupe);
arrContainer.should.not.contain(arrNeedle);
arrContainer.should.not.contain(objNeedle); // fails
objContainer.arr.should.not.equal(arrNeedle);
objContainer.obj.should.not.equal(objNeedle);
});
在测试中我们正在克隆一个对象并将其插入到数组中:
objNeedle = {w: 'waffles'}; // original
objDupe = JSON.parse(JSON.stringify(objNeedle)); // clone
arrContainer = [arrDupe, objDupe, strDupe, numDupe]; // add clone to array
失败的断言检查数组(包含克隆的对象)不包含原始对象。
arrContainer.should.not.contain(objNeedle); // fails
我尝试使用外部断言插入(chai-things)但没有成功:
arrContainer.should.not.include(objNeedle); // fails
arrContainer.should.not.include.something.that.deep.equals(objNeedle); // fails
以下断言通过了测试但不是理想的解决方案:
arrContainer[0].should.not.equal(objNeedle); // pass
你知道为什么数组只在某些情况下被认为等于它的克隆吗?
提前致谢:)
如果您查看 ChaiJS 代码,您将在 line 189 of /lib/chai/core/assertions.js 上看到以下内容:
if (_.type(obj) === 'array' && _.type(val) === 'object') {
for (var i in obj) {
if (_.eql(obj[i], val)) {
expected = true;
break;
}
}
}
这在 include(val, msg)
函数内部,这是 .contains()
匹配器使用的函数(参见 line 215)。
这意味着如果 obj
(被测试的东西)是一个数组并且 val
(.contains()
匹配器函数的参数)是一个对象,因为它在您的情况下,它将使用 _.eql()
检查深度相等性(_.eql
是外部 deep-eql
模块的函数 provided/exported 的别名)。
我在 JavaScript 单元测试中发现了一个我想要修复的失败断言。单元测试代码如下(完整代码可见here):
beforeEach(function() {
arrNeedle = ['waffles'];
objNeedle = {w: 'waffles'};
strNeedle = 'waffles';
numNeedle = 3.14159
arrDupe = JSON.parse(JSON.stringify(arrNeedle));
objDupe = JSON.parse(JSON.stringify(objNeedle));
strDupe = JSON.parse(JSON.stringify(strNeedle));
numDupe = JSON.parse(JSON.stringify(numNeedle));
arrContainer = [arrDupe, objDupe, strDupe, numDupe];
objContainer = {
arr: arrDupe
, obj: objDupe
, str: strDupe
, num: numDupe
};
arrMissing = ['chan'];
objMissing = {missing: 'chan'}
strMissing = 'chan';
});
it("has its test set up correctly", function() {
arrNeedle.should.not.equal(arrDupe);
objNeedle.should.not.equal(objDupe);
arrContainer.should.not.contain(arrNeedle);
arrContainer.should.not.contain(objNeedle); // fails
objContainer.arr.should.not.equal(arrNeedle);
objContainer.obj.should.not.equal(objNeedle);
});
在测试中我们正在克隆一个对象并将其插入到数组中:
objNeedle = {w: 'waffles'}; // original
objDupe = JSON.parse(JSON.stringify(objNeedle)); // clone
arrContainer = [arrDupe, objDupe, strDupe, numDupe]; // add clone to array
失败的断言检查数组(包含克隆的对象)不包含原始对象。
arrContainer.should.not.contain(objNeedle); // fails
我尝试使用外部断言插入(chai-things)但没有成功:
arrContainer.should.not.include(objNeedle); // fails
arrContainer.should.not.include.something.that.deep.equals(objNeedle); // fails
以下断言通过了测试但不是理想的解决方案:
arrContainer[0].should.not.equal(objNeedle); // pass
你知道为什么数组只在某些情况下被认为等于它的克隆吗?
提前致谢:)
如果您查看 ChaiJS 代码,您将在 line 189 of /lib/chai/core/assertions.js 上看到以下内容:
if (_.type(obj) === 'array' && _.type(val) === 'object') {
for (var i in obj) {
if (_.eql(obj[i], val)) {
expected = true;
break;
}
}
}
这在 include(val, msg)
函数内部,这是 .contains()
匹配器使用的函数(参见 line 215)。
这意味着如果 obj
(被测试的东西)是一个数组并且 val
(.contains()
匹配器函数的参数)是一个对象,因为它在您的情况下,它将使用 _.eql()
检查深度相等性(_.eql
是外部 deep-eql
模块的函数 provided/exported 的别名)。