【问题标题】:Chai - Testing for values in array of objectsChai - 测试对象数组中的值
【发布时间】:2017-01-18 17:53:15
【问题描述】:

我正在将我的测试结果设置到一个 REST 端点,该端点返回一个 Mongo 数据库对象数组。

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

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

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

谢谢

【问题讨论】:

    标签: javascript arrays mocha.js chai


    【解决方案1】:

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

    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']);
    

    如果你知道返回数组的顺序,你也可以这样做:

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

    【讨论】:

    • 谢谢。因为我不能保证结果顺序,所以可以解决我想要测试的问题
    • 我想提一下,虽然您的答案是正确的,但最好使用.map() 而不是.forEach()push() 结合使用。 Map 比 forEach [1] 更快并且更具可读性。 :) [1] codeburst.io/javascript-map-vs-foreach-f38111822c0f
    【解决方案2】:

    正如here 所述,以下代码现在可以与chai-like@0.2.14chai-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'});
    

    【讨论】:

      【解决方案3】:

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

      这会检查无序的完全相等。 (对于不完全等式更改membersincludes

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

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

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

      【讨论】:

        【解决方案4】:

        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/

        【讨论】:

          【解决方案5】:

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

          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');
          

          【讨论】:

            【解决方案6】:

            我喜欢@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'));
            

            【讨论】:

              【解决方案7】:

              另一种解决方案是使用函数扩展数组对象,以测试数组中是否存在所需属性与预期值匹配的对象,如下所示

              /**
               * @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);
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2018-08-09
                • 2017-11-19
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-11-04
                相关资源
                最近更新 更多