在NodeJS中testing对象相等

我们正在编写一个程序的testing。 我们要编写一个函数testing来validation程序的输出是否符合某些期望。 返回的对象是一个复杂的JS对象(嵌套对象,许多属性等)。

我们想testing一下,这显然匹配我们所需要的。 到目前为止,我们正在浏览对象和预期的结果,检查每个属性和每个嵌套的对象。 这是非常麻烦的,我们想知道是否有任何图书馆“build立”所有的testing,只是基于对象。 例如这样的东西。

var res = { a: { alpha: [1,2,3], beta: "Hello", gamma: "World" }, }, b: 123, c: "It depends" } }; var expectation = { a: { alpha: [1,2,4], beta: "Hello", gamma: "World" }, }, b: 123, c: "It depends" } }; assert(res, expectation) // -> Raises an error because res[a][b][2] is different from expectation[a][b][2]. 

[在这个例子中,我简化了对象的复杂性…]

我应该坚持这样一个事实,即我们需要一段足够聪明的代码来告诉我们不同的东西,而不是仅仅告诉我们这两个对象是不同的。 我们现在谈到深层次的平等,但是我们还没有发现任何能够真正告诉我们差异的东西。

节点具有用于testing的内置断言模块。 这有一个深度平等检查方法称为deepEqual

函数签名是:

 assert.deepEqual(actual, expected, [message]) 

快速编写testingdeepEquality和返回diff的函数:

 // Will test own properties only function deepEqualWithDiff(a, e, names){ var dif = {}; var aKeys = Object.keys(a); var eKeys = Object.keys(e); var cKeys = aKeys; var dKeys = eKeys; var c = a; var d = e; var names = { c: names ? names['a'] : 'Actual', d: names ? names['e'] : 'Expected' } if(eKeys.length > aKeys.length){ cKeys = eKeys; dKeys = aKeys; c = e; d = a; names = { d: names ? names['a'] : 'Actual', c: names ? names['e'] : 'Expected' } } for(var i = 0, co = cKeys.length; i < co; i++){ var key = cKeys[i]; if(typeof c[key] !== typeof d[key]){ dif[key] = 'Type mismatch ' + names['c'] + ':' + typeof c[key] + '!==' + names['d'] + typeof d[key]; continue; } if(typeof c[key] === 'function'){ if(c[key].toString() !== d[key].toString()){ dif[key] = 'Differing functions'; } continue; } if(typeof c[key] === 'object'){ if(c[key].length !== undefined){ // array var temp = c[key].slice(0); temp = temp.filter(function(el){ return (d[key].indexOf(el) === -1); }); var message = ''; if(temp.length > 0){ message += names['c'] + ' excess ' + JSON.stringify(temp); } temp = d[key].slice(0); temp = temp.filter(function(el){ return (c[key].indexOf(el) === -1); }); if(temp.length > 0){ message += ' and ' + names['d'] + ' excess ' + JSON.stringify(temp); } if(message !== ''){ dif[key] = message; } continue; } var diff = deepEqualWithDiff(c[key], d[key], {a:names['c'],e:names['d']}); if(diff !== true && Object.keys(diff).length > 0){ dif[key] = diff; } continue; } // Simple types left so if(c[key] !== d[key]){ dif[key] = names['c'] + ':' + c[key] + ' !== ' + names['d'] + ':' + d[key]; } } return Object.keys(dif).length > 0 ? dif : true; } 

JavaScript并不支持开箱即用的对象深入的平等,而且我也没有意识到NodeJS API中内置的任何东西。

我打赌可能是下划线和isEqual函数。

npm安装下划线

 var _ = require('underscore'); var moe = {name : 'moe', luckyNumbers : [13, 27, 34]}; var clone = {name : 'moe', luckyNumbers : [13, 27, 34]}; moe == clone; => false _.isEqual(moe, clone); => true 

虽然大多数Nodetesting框架也应该包含一个对象深层的相等断言,但是你没有提到你正在使用哪一个。

深度差异是OP所要求的。 它可以比较两个javascript对象/ JSON对象,并以代码可以访问的方式列出差异。

这是一个古老的问题,所以这个图书馆在提问时可能不存在。

虽然我认为已经介绍了对象比较的基础知识(请参阅此处和其他内容),但是如果您正在寻找一种快速而肮脏的方法来执行这些testing,并查看两个不相等的对象之间的差异,则可以运行在Webstorm IDE中使用nodeunit进行testing( 此处 )

Webstorm与nodeunit集成得非常好,并且对于任何test.equals()或test.deepEquals()断言,它都提供了一个可见的diff,其中突出显示了您的descreence。 我强烈推荐IDE将它的testing集成到我的js开发周期中。

现在,如果你需要在你的代码中能够访问test / diff的结果,这对你来说显然是不够的,我build议你从我列出的第一个链接中复制一些deepEquals比较器。

祝你好运,

布赖恩

这是我用Lodash写的简单/灵活的深度差异函数:

 _.merge(obj1, obj2, function (objectValue, sourceValue, key, object, source) { if ( !(_.isEqual(objectValue, sourceValue)) && (Object(objectValue) !== objectValue)) { console.log(key + "\n Expected: " + sourceValue + "\n Actual: " + objectValue); } });