javascript - 在 NodeJS 中测试对象相等性

标签 javascript node.js testing

我们正在为一个程序编写测试。我们想编写一个功能测试来验证程序的输出是否符合某些期望。 返回的对象是一个复杂的 JS 对象(具有嵌套对象、许多属性……等等)。

我们想测试这显然符合我们的需要。 到目前为止,我们一直在“浏览”对象和预期结果,检查每个属性和每个嵌套对象。这非常麻烦,我们想知道是否有任何库可以“构建”所有测试,仅基于对象。比如这样的事情。

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].

[在示例中,我简化了对象的复杂性...]

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

最佳答案

Node 内置了 assert用于测试的模块。这有一个名为 deepEqual 的方法,用于深度相等检查。

函数签名是:

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

用于测试 deepEquality 并返回 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 中测试对象相等性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12629981/

相关文章:

node.js - es6 导出/导入多个类 - instanceof 返回 false

javascript - 无法在javascript中调用null的方法 'toString'-nodejs

testing - 强制 FsCheck 生成 NonEmptyString,用于区分字符串类型的联合字段

javascript - 无法使用 mocha 和 supertest 测试 OPTIONS 方法

c# - Jquery 拖放 - 无法拖回

javascript - 如何防止 CTRL + P 在 Mozilla 中打印对话框

javascript - 当我省略/需要 Prop 时,为什么受歧视的工会不起作用?

javascript - 如何在javascript中验证多选数组是否为空?

node.js - Nodejs 中多个端口的 ElasticBeanStalk NGinx 配置

python-分割数据集以获得高性能准确性的最佳技术