如何测试对象的可选成员

How to Test an optional member of an object?

本文关键字:成员 对象 何测试 测试      更新时间:2023-09-26

测试可选对象成员的最佳技术是什么? 现在,我们在期望语句前面加上一个if:

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

但是必须有一种在风格上更内联的方法。 例如

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

或(移动可选以提供期望的替代版本(:

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

update - 我开始编写这段代码(柴的新手(,看看我是否可以完成我的目标,所以我添加了一个小插件:

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

我认为实现有点笨拙 - 但胖箭头函数会削弱一些语法。所以在这里等待!

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

在阅读了chai的插件指南后,我会使用类似的方法来使用标志。但是,我得出了同样的结论-您不能简单地停止链条。

我的一种可能性不仅是实现新属性和新标志,而且覆盖assert方法本身 - 在设置当前Assertion对象上的OPTIONAL_FLAG标志时不抛出。但是,破坏一切或错过边缘情况的机会太高了。

毕竟,我认为这不是一个好主意。引用这个"令人困惑的语法"问题:

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

设计Chai的链式断言的挑战在于找到 表现力和简洁之间的平衡。即使完整的语法 实施和记录并不是一项艰巨的任务,它将使 API 不太简洁,这对测试环境不利。

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

这意味着不可能实现像.or运算符这样的东西。

不过,可能的是实现类似的东西

either(function(){
    expect(object).not.to.have.a.property('member');
}).or(function(){
    expect(object).to.have.a.property('member').that.is.a('string');
});

也许可以在此基础上构建更具吸引力的语法。