如何测试对象的可选成员?

时间:2014-09-10 14:11:39

标签: javascript node.js chai

测试可选对象成员的最佳技术是什么。现在我们正在使用if:

为expect语句添加前缀
 if(object.member) expect(object).to.have.a.property('member').that.is.a('string');

但必须有一种风格更内联的方法。 E.g。

 expect(object).to.have.an.optional.property('member').that.is.a('string');

或(为了便于阅读,添加为空链):

 expect(object).to.have.an.optional.property('member').that.would.be.a('string');

或(移动可选项以提供expect的替代版本):

 optionally.expect(object).to.have.a.property('member').that.is.a('string');

更新 - 我开始编写此代码(chai的新内容),看看我是否可以完成我的定位,所以我添加了一个小插件:

module.exports = function(chai, utils) {
    var Assertion = chai.Assertion
        , i = utils.inspect
        , flag = utils.flag;

    var OPTIONAL_FLAG = 'chai-optional/option'
    Assertion.addProperty('optional', function() {
        flag(this, OPTIONAL_FLAG, true)
        return this;
    })

    Assertion.overwriteMethod('property', function (_super) {
        return function assertProperty (propertyName) {
            if (flag(this, OPTIONAL_FLAG)) {
                flag(this, OPTIONAL_FLAG, false) ;

                var obj = this._obj;
                var isPropertyPresent = (obj[propertyName]) ? true : false ;

                if(isPropertyPresent) {
                    return _super.apply(this, arguments);
                }

            } else {
                _super.apply(this, arguments);
            }
        };
    });

    Assertion.addProperty('would', function () {
        return this;
    });
};

用法:

it('could be null or have a value', function(done){
    var objWithout = {}
    var objWith = {}
    objWith.someProperty = 'blah'

    expect(objWith).to.have.optional.property('someProperty').that.would.be.a('string');
    expect(objWithout).to.have.optional.property('someProperty').that.would.be.a('string');

    return done();
})

当前问题即使属性不存在,功能的控制也会结束 - 但评估链仍在继续。我需要在没有断言的情况下结束评估 - 这可能吗?


更新任一解决方案(简单化解决方案):

var either = function(firstCondition){
    var returnObject = {}

    try{
        firstCondition()
        returnObject.or = function(secondCondition){ return }
    } catch(e) {
        returnObject.or = function(secondCondition){ return secondCondition() }
    }
    return returnObject ;
}

module.exports = either

我认为实现有点笨重 - 但胖箭头功能会使一些语法变得稀疏。所以这里等着!

1 个答案:

答案 0 :(得分:0)

  

当前问题即使属性不存在,函数的控制也会结束 - 但评估链仍在继续。我需要在没有断言的情况下结束评估 - 这可能吗?

在阅读了关于chai的plugin guide之后,我会使用类似的方法来标记。但是,我得出了同样的结论 - 你不能简单地停止链条。

我可能不仅要实现新属性和新标志,而且要覆盖assert方法本身 - 当前{{1}上的OPTIONAL_FLAG标志时不抛出对象已设置。然而,摧毁一切或错过边缘案件的机会太高了。

毕竟,我认为这不是一个好主意。引自this "confusing syntax" issue

  

我认为这种误解来自你对柴的期望   遵循大多数/所有英语语法规则。不幸的是,英语语法   它有太多的规则(以及那些规则的例外),因为它是一个   合理的承诺实施。

     

设计Chai的可连锁断言的挑战在于寻找   表达和简洁之间的平衡。即使是完整的语法   实施和记录并不是一项艰巨的任务,它将成为   API不够简洁,这对测试环境不利。

     
    

规则:任何修改断言行为的“标志”(否定     一旦设置为true,则不包含include包含/包含等等     应该保持真实,直到链的末端。

  

这意味着不可能像Assertion运算符那样实现。

虽然可以实现像

这样的东西
.or

也许有人可以在其上构建更具吸引力的语法。