我正在为我的应用程序使用node,mocha和chai。我想测试我的返回结果数据属性与我的模型对象之一是“对象类型”。 (与柴的实例非常相似)。我只是想确认这两个对象具有相同的属性名称集。 我对这些属性的实际值不感兴趣。
让我说我有像下面这样的模特人物。我想检查我的results.data是否具有与预期模型相同的属性。所以在这种情况下,Person具有firstName和lastName。
因此,如果results.data.lastName
和results.data.firstName
都存在,那么它应该返回true。如果其中任何一个不存在,则应返回false。如果results.data具有任何其他属性(如results.data.surname),那么它将返回false,因为在Person中不存在姓氏。
模型
function Person(data) {
var self = this;
self.firstName = "unknown";
self.lastName = "unknown";
if (typeof data != "undefined") {
self.firstName = data.firstName;
self.lastName = data.lastName;
}
}
答案 0 :(得分:82)
您可以序列化简单数据以检查是否相等:
data1 = {firstName: 'John', lastName: 'Smith'};
data2 = {firstName: 'Jane', lastName: 'Smith'};
JSON.stringify(data1) === JSON.stringify(data2)
这会给你类似的东西
'{firstName:"John",lastName:"Smith"}' === '{firstName:"Jane",lastName:"Smith"}'
作为一种功能......
function compare(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}
compare(data1, data2);
如果你像你说的那样使用柴,请查看http://chaijs.com/api/bdd/#equal-section
如果你只想检查钥匙......
function compareKeys(a, b) {
var aKeys = Object.keys(a).sort();
var bKeys = Object.keys(b).sort();
return JSON.stringify(aKeys) === JSON.stringify(bKeys);
}
应该这样做。
答案 1 :(得分:23)
2这是一个简短的 ES6 可变参数版本:
function objectsHaveSameKeys(...objects) {
const allKeys = objects.reduce((keys, object) => keys.concat(Object.keys(object)), []);
const union = new Set(allKeys);
return objects.every(object => union.size === Object.keys(object).length);
}
一点性能测试(MacBook Pro - 2,8 GHz Intel Core i7,Node 5.5.0):
var x = {};
var y = {};
for (var i = 0; i < 5000000; ++i) {
x[i] = i;
y[i] = i;
}
结果:
objectsHaveSameKeys(x, y) // took 4996 milliseconds
compareKeys(x, y) // took 14880 milliseconds
hasSameProps(x,y) // after 10 minutes I stopped execution
答案 2 :(得分:9)
如果要检查两个对象是否具有相同的属性名称,可以执行以下操作:
function hasSameProps( obj1, obj2 ) {
return Object.keys( obj1 ).every( function( prop ) {
return obj2.hasOwnProperty( prop );
});
}
var obj1 = { prop1: 'hello', prop2: 'world', prop3: [1,2,3,4,5] },
obj2 = { prop1: 'hello', prop2: 'world', prop3: [1,2,3,4,5] };
console.log(hasSameProps(obj1, obj2));
通过这种方式,您确定只检查两个对象的可迭代和可访问属性。
编辑 - 2013.04.26:
可以通过以下方式重写上一个功能:
function hasSameProps( obj1, obj2 ) {
var obj1Props = Object.keys( obj1 ),
obj2Props = Object.keys( obj2 );
if ( obj1Props.length == obj2Props.length ) {
return obj1Props.every( function( prop ) {
return obj2Props.indexOf( prop ) >= 0;
});
}
return false;
}
通过这种方式,我们检查两个对象是否具有相同数量的属性(否则对象具有相同的属性,并且我们必须返回逻辑假)然后,如果数字匹配,我们将检查它们是否匹配具有相同的属性。
<强>加成强>
可能的增强功能可能是引入类型检查以强制执行每个属性的匹配。
答案 3 :(得分:7)
如果您需要像@speculees这样的深度验证,请使用deep-keys
进行回答(披露:我是这个小包装的维护者)
// obj1 should have all of obj2's properties
var deepKeys = require('deep-keys');
var _ = require('underscore');
assert(0 === _.difference(deepKeys(obj2), deepKeys(obj1)).length);
// obj1 should have exactly obj2's properties
var deepKeys = require('deep-keys');
var _ = require('lodash');
assert(0 === _.xor(deepKeys(obj2), deepKeys(obj1)).length);
或chai
:
var expect = require('chai').expect;
var deepKeys = require('deep-keys');
// obj1 should have all of obj2's properties
expect(deepKeys(obj1)).to.include.members(deepKeys(obj2));
// obj1 should have exactly obj2's properties
expect(deepKeys(obj1)).to.have.members(deepKeys(obj2));
答案 4 :(得分:1)
这是schirrmacher上面提供的函数的深度检查版本 下面是我的尝试。请注意:
function objectsHaveSameKeys(...objects) {
const allKeys = objects.reduce((keys, object) => keys.concat(Object.keys(object)), [])
const union = new Set(allKeys)
if (union.size === 0) return true
if (!objects.every((object) => union.size === Object.keys(object).length)) return false
for (let key of union.keys()) {
let res = objects.map((o) => (typeof o[key] === 'object' ? o[key] : {}))
if (!objectsHaveSameKeys(...res)) return false
}
return true
}
答案 5 :(得分:-1)
这是我尝试验证JSON属性。我使用@ casey-foster的方法,但添加了递归以进行更深入的验证。函数中的第三个参数是可选的,仅用于测试。
//compare json2 to json1
function isValidJson(json1, json2, showInConsole) {
if (!showInConsole)
showInConsole = false;
var aKeys = Object.keys(json1).sort();
var bKeys = Object.keys(json2).sort();
for (var i = 0; i < aKeys.length; i++) {
if (showInConsole)
console.log("---------" + JSON.stringify(aKeys[i]) + " " + JSON.stringify(bKeys[i]))
if (JSON.stringify(aKeys[i]) === JSON.stringify(bKeys[i])) {
if (typeof json1[aKeys[i]] === 'object'){ // contains another obj
if (showInConsole)
console.log("Entering " + JSON.stringify(aKeys[i]))
if (!isValidJson(json1[aKeys[i]], json2[bKeys[i]], showInConsole))
return false; // if recursive validation fails
if (showInConsole)
console.log("Leaving " + JSON.stringify(aKeys[i]))
}
} else {
console.warn("validation failed at " + aKeys[i]);
return false; // if attribute names dont mactch
}
}
return true;
}
答案 6 :(得分:-1)
如果您使用的是underscoreJs,那么您只需使用_.isEqual函数即可 并且它比较了每个层次结构的所有键和值,如下例所示。
var object = {"status":"inserted","id":"5799acb792b0525e05ba074c","data":{"workout":[{"set":[{"setNo":1,"exercises":[{"name":"hjkh","type":"Reps","category":"Cardio","set":{"reps":5}}],"isLastSet":false,"index":0,"isStart":true,"startDuration":1469689001989,"isEnd":true,"endDuration":1469689003323,"speed":"00:00:01"}],"setType":"Set","isSuper":false,"index":0}],"time":"2016-07-28T06:56:52.800Z"}};
var object1 = {"status":"inserted","id":"5799acb792b0525e05ba074c","data":{"workout":[{"set":[{"setNo":1,"exercises":[{"name":"hjkh","type":"Reps","category":"Cardio","set":{"reps":5}}],"isLastSet":false,"index":0,"isStart":true,"startDuration":1469689001989,"isEnd":true,"endDuration":1469689003323,"speed":"00:00:01"}],"setType":"Set","isSuper":false,"index":0}],"time":"2016-07-28T06:56:52.800Z"}};
console.log(_.isEqual(object, object1));//return true
如果这些键的所有键和值在两个对象中都相同,那么它将返回true,否则返回false。
答案 7 :(得分:-2)
要比较两个对象及其所有属性,我遵循以下代码,并且不需要tostring()或json比较器
if(user1.equals(user2))
{
console.log("Both are equal");
}
e。