寻找Chai框架中检查对象仅含指定键的only替代断言方法
Chai断言:替代
only实现对象仅含指定允许键的验证方案 我刚好遇到过类似的需求,Chai原生的only关键词是做严格键匹配(要求对象的键集合和指定的完全一致,不能多也不能少),但你需要的逻辑是:对象的所有键都必须属于指定的允许列表,允许对象缺少列表中的键,但绝对不能有列表外的额外键。下面给你几个可行的替代方案:
方案1:使用原生函数直接验证
最简单直接的方式是写一个辅助函数,检查对象的所有键是否都在允许列表内,然后用Chai的基础断言验证结果:
// 辅助函数:检查对象的所有键都属于允许列表 const hasNoExtraKeys = (obj, allowedKeys) => { const objKeys = Object.keys(obj); // 确保对象的每个键都在允许列表中 return objKeys.every(key => allowedKeys.includes(key)); }; // 对应你的三个测试场景 chai.expect(hasNoExtraKeys({ x: 1, z: 1 }, ["x", "y"])).to.be.false; // 断言失败(存在额外键z) chai.expect(hasNoExtraKeys({}, ["x", "y"])).to.be.true; // 断言通过(无额外键) chai.expect(hasNoExtraKeys({ x: 1 }, ["x", "y"])).to.be.true; // 断言通过(所有键都在允许列表内)
这个方案的优点是零配置,适合临时或少量使用的场景。
方案2:借助Chai的to.satisfy保持链式风格
如果你想保留Chai的链式调用习惯,可以用to.satisfy方法,传入一个验证回调:
// 场景1:存在额外键,断言失败 chai.expect({ x: 1, z: 1 }).to.satisfy(obj => Object.keys(obj).every(key => ["x", "y"].includes(key)) ); // 场景2:空对象,断言通过 chai.expect({}).to.satisfy(obj => Object.keys(obj).every(key => ["x", "y"].includes(key)) ); // 场景3:仅含允许键,断言通过 chai.expect({ x: 1 }).to.satisfy(obj => Object.keys(obj).every(key => ["x", "y"].includes(key)) );
这种方式不需要额外写辅助函数,链式调用更符合Chai的使用习惯,但每次都要重复写回调逻辑,适合零散使用的场景。
方案3:自定义Chai断言(推荐)
如果你的项目中频繁需要这种验证,最优雅的方式是自定义一个Chai断言,让它像原生方法一样链式调用,还能提供友好的错误提示:
// 注册自定义断言插件 chai.use((chai, utils) => { const Assertion = chai.Assertion; // 添加名为onlyAllowedKeys的断言方法 Assertion.addMethod('onlyAllowedKeys', function(...allowedKeys) { // 获取断言的目标对象 const obj = utils.flag(this, 'object'); const objKeys = Object.keys(obj); // 找出所有不在允许列表中的额外键 const extraKeys = objKeys.filter(key => !allowedKeys.includes(key)); // 执行断言检查 this.assert( extraKeys.length === 0, `expected object to only contain keys from [${allowedKeys.join(', ')}], but found extra key(s): [${extraKeys.join(', ')}]`, `expected object to have extra keys not in [${allowedKeys.join(', ')}]` ); }); }); // 现在可以像原生Chai方法一样使用了 chai.expect({ x: 1, z: 1 }).to.onlyAllowedKeys("x", "y"); // 断言失败,提示"found extra key(s): [z]" chai.expect({}).to.onlyAllowedKeys("x", "y"); // 断言通过 chai.expect({ x: 1 }).to.onlyAllowedKeys("x", "y"); // 断言通过
这个方案的优点是代码复用性高,错误提示清晰,完全符合Chai的使用体验,适合长期频繁使用的场景。
内容的提问来源于stack exchange,提问作者xercool
相关产品推荐
相关产品推荐

