如何在Chai中深度比较对象时校验指定属性的类型
Chai深度断言API响应时处理未知属性的方案
假设我们调用Restful Booker API的GET预订接口,得到如下响应:
{ "bookingid": 4693, "booking": { "firstname": "firstname", "lastname": "lastname", "totalprice": 9999, "depositpaid": false, "bookingdates": { "checkin": "2018-01-01", "checkout": "2019-01-01" }, "additionalneeds": "additional needs" } }
我希望用Chai的深度断言直接对比完整对象,避免逐属性断言,理想的断言结构类似:
expect(response.data).to.deep.equal({ bookingid: ?, // 这里的值未知,需要断言它是数字/整数 booking: { firstname: 'firstname', lastname: 'lastname', totalprice: 9999, depositpaid: false, bookingdates: { checkin: '2018-01-01', checkout: '2019-01-01' }, additionalneeds: 'additional needs' } });
现在有两个问题:
- 能否在保持这种整体结构的前提下,仅断言
bookingid为数字/整数? - 这种方法是否常用,有没有不推荐的理由?
实现方法
当然可以实现,以下几种思路能兼顾整体结构和未知属性的类型验证:
方法1:拆分断言但保持逻辑关联
先单独验证bookingid的类型,再用深度断言匹配已知的booking对象,既保留整体结构的验证,又处理了未知属性:
// 验证bookingid是整数 expect(response.data.bookingid).to.be.an('integer'); // 深度匹配已知的booking对象结构 expect(response.data.booking).to.deep.equal({ firstname: 'firstname', lastname: 'lastname', totalprice: 9999, depositpaid: false, bookingdates: { checkin: '2018-01-01', checkout: '2019-01-01' }, additionalneeds: 'additional needs' }); // 可选:验证响应仅包含这两个属性 expect(response.data).to.have.all.keys('bookingid', 'booking');
方法2:用satisfy包裹整体断言
如果想把所有断言逻辑放在一个代码块里,可使用Chai的satisfy方法,在回调中完成类型验证和深度匹配:
expect(response.data).to.satisfy(data => { // 验证bookingid是整数 expect(data.bookingid).to.be.an('integer'); // 验证booking对象完全匹配 expect(data.booking).to.deep.equal({ firstname: 'firstname', lastname: 'lastname', totalprice: 9999, depositpaid: false, bookingdates: { checkin: '2018-01-01', checkout: '2019-01-01' }, additionalneeds: 'additional needs' }); // 必须返回true表示满足断言条件 return true; });
方法3:结合deep.include和类型断言
如果API可能返回不影响业务的额外属性,用deep.include匹配已知部分,同时单独验证bookingid:
expect(response.data).to.deep.include({ booking: { firstname: 'firstname', lastname: 'lastname', totalprice: 9999, depositpaid: false, bookingdates: { checkin: '2018-01-01', checkout: '2019-01-01' }, additionalneeds: 'additional needs' } }); expect(response.data.bookingid).to.be.an('integer');
方法的实用性与注意事项
- 是否常用? 这种混合类型验证和深度匹配的方法在接口测试中很常见,尤其适用于大部分属性固定、少数属性为动态生成(如ID、时间戳)的场景,能有效减少断言代码冗余。
- 不推荐的场景:
- 当接口返回的对象结构极复杂、嵌套层级过深时,这种断言会变得难以维护,不如逐关键属性断言清晰。
- 若使用
deep.equal做完全匹配,一旦API新增非预期属性,断言会直接失败——如果这些新增属性不影响业务,反而会导致测试用例误报,这种场景下用deep.include更稳妥。 - 若
bookingid有更严格的规则(如范围、非负数),仅验证类型会遗漏边界条件,需要补充对应断言。
内容的提问来源于stack exchange,提问作者Hans
相关产品推荐
相关产品推荐

