Chai - 测试 objects 数组中的值

Chai - Testing for values in array of objects

我正在将我的结果测试设置到一个 REST 端点,return我是一个 Mongo 数据库数组 objects。

[{_id: 5, title: 'Blah', owner: 'Ted', description: 'something'...},
 {_id: 70, title: 'GGG', owner: 'Ted', description: 'something'...}...]

我想让我的测试验证的是,在 return 数组中,它包含应该 return 的特定标题。我使用 Chai/Chai-Things 所做的一切似乎都不起作用。我假设 res.body.savedResults.should.include.something.that.equals({title: 'Blah'}) 错误,因为记录 object 包含除标题之外的其他键和值。

有没有办法让它做我想做的事?我只需要验证标题在数组中,而不关心其他数据可能是什么 (IE _id)。

谢谢

这是我在测试中通常做的事情:

var result = query_result;

var members = [];
result.forEach(function(e){
    members.push(e.title);
});

expect(members).to.have.members(['expected_title_1','expected_title_2']);

如果您知道 return 数组的顺序,您也可以这样做:

expect(result).to.have.deep.property('[0].title', 'expected_title_1');
expect(result).to.have.deep.property('[1].title', 'expected_title_2');

另一种解决方案是用一个函数扩展数组对象,以测试数组中是否存在一个对象,其所需的 属性 与预期值匹配,就像这样

/**
 * @return {boolean}
 */
Array.prototype.HasObjectWithPropertyValue = function (key, value) {
    for (var i = 0; i < this.length; i++) {
        if (this[i][key] === value) return true;
    }
    return false;
};

(我把它放在我的主 test.js 文件中,以便所有其他嵌套测试都可以使用该函数)

然后你可以像这样在你的测试中使用它

var result = query_result;
// in my case (using superagent request) here goes
// var result = res.body;

result.HasObjectWithPropertyValue('property', someValue).should.equal(true);

如所述 following code works now with chai-like@0.2.14 and chai-things。我只是喜欢这种方法的自然可读性。

var chai = require('chai'),
    expect = chai.expect;

chai.use(require('chai-like'));
chai.use(require('chai-things')); // Don't swap these two

expect(data).to.be.an('array').that.contains.something.like({title: 'Blah'});

这是我发现更有用的另一种方法。基本上,使用字符串插值并将对象数组映射到字符串文字数组。然后你可以对字符串数组写期望。

const locations: GeoPoint[] = [
  {
    latitude: 10,
    longitude: 10
  },
  {
    latitude: 9,
    longitude: 9
  },
  {
    latitude: -10,
    longitude: -10
  },
  {
    latitude: -9,
    longitude: -9
  }
];
const stringLocations: string[] = locations.map((val: GeoPoint) => 
  `${val.latitude},${val.longitude}`
);

expect(stringLocations).to.contain('-9.5,-9.5');
expect(stringLocations).to.contain('9.5,9.5');

现在最好的方法可能是使用 deep.members 属性

这会检查无序的完全相等性。 (对于 includes 的不完全相等更改 members

expect([ {a:1} ]).to.have.deep.members([ {a:1} ]); // passes
expect([ {a:1} ]).to.have.members([ {a:1} ]); // fails

这是一篇关于测试数组的很棒的文章和objects https://medium.com/building-ibotta/testing-arrays-and-objects-with-chai-js-4b372310fe6d

免责声明:这不仅是为了测试 title属性,而是为了测试整个 objects

ES6+

简洁、实用且无依赖性,只需使用映射来过滤您要检查的键

类似于:

const data = [{_id: 5, title: 'Blah', owner: 'Ted', description: 'something'},{_id: 70, title: 'GGG', owner: 'Ted', description: 'something'}];


expect(data.map(e=>({title:e.title}))).to.include({title:"Blah"});

如果您只检查一个键,甚至更短:

expect(data.map(e=>(e.title))).to.include("Blah");

https://www.chaijs.com/api/bdd/

我喜欢@sebastien-horin 的建议 但是另一种方式with Should syntax(针对特定的属性):

const data = [
    { _id: 5, title: 'Blah', owner: 'Ted', description: 'something' },
    { _id: 7, title: 'Test', owner: 'Ted', description: 'something' },
];

data.map((e) => e.title).every((title) => title.should.equal('Blah'));