能否用Jest递归遍历对象?无需Lodash如何检查属性是否存在
嘿,这两个问题我都能帮你搞定!
Jest本身并没有内置专门用来递归遍历对象的工具函数,但你完全可以结合JavaScript原生的递归逻辑,搭配Jest的断言方法来实现这个需求。
比如如果你想递归检查对象里所有的字符串属性都不为空,可以写一个简单的递归函数,在里面调用Jest的断言:
function assertAllStringsNotEmpty(obj) { for (const key in obj) { const value = obj[key]; if (typeof value === 'object' && value !== null) { // 递归处理嵌套对象 assertAllStringsNotEmpty(value); } else if (typeof value === 'string') { // 用Jest断言字符串不为空 expect(value).not.toBe(''); } } } // 调用这个函数来检查你的响应对象 assertAllStringsNotEmpty(res.body.result);
本质上就是用JS原生的递归遍历逻辑,把Jest的断言作为遍历过程中的检查动作,完全可以满足需求。
你遇到的问题是:当响应不是成功状态时,直接链式访问res.body.result.verificationToken会触发JavaScript的TypeError(因为res.body.result可能不存在),而不是优雅地断言失败。不用Lodash的话,有几种纯Jest+原生JS的解决方案:
方法一:用可选链操作符(最简洁)
ES2020引入的可选链?.可以安全访问嵌套属性,当某一层不存在时会返回undefined,不会抛出错误。配合Jest的toBeDefined()就能实现安全断言:
expect(res.body.result?.verificationToken).toBeDefined();
如果res.body.result不存在,res.body.result?.verificationToken会返回undefined,此时toBeDefined()会断言失败,但不会抛出JS错误,正好符合你“先检查属性是否存在”的需求。
方法二:用Jest的expect.objectContaining嵌套断言
如果你想更严谨地验证每一层的结构,可以用Jest的expect.objectContaining来嵌套检查对象是否包含指定属性:
expect(res.body).toEqual( expect.objectContaining({ result: expect.objectContaining({ verificationToken: expect.toBeDefined() }) }) );
这个方法的好处是不仅能检查verificationToken是否存在,还能验证res.body和res.body.result都是对象类型,断言失败时的错误信息也会更清晰,告诉你哪一层结构不符合预期。
方法三:手动逐层检查(兼容旧环境)
如果你的运行环境不支持可选链,可以手动逐层判断属性是否存在,再进行断言:
// 先检查res.body是否存在 expect(res.body).toBeDefined(); // 再检查res.body.result是否存在 if (res.body.result) { expect(res.body.result.verificationToken).toBeDefined(); }
这种方式虽然代码多一点,但兼容性最好,适合旧项目场景。
内容的提问来源于stack exchange,提问作者Tahsin

