5月27日 19:55

Jest 断言方法有哪些?expect 和匹配器怎么用?

Jest 断言就一个套路:expect(实际值).匹配器(期望值)。匹配器决定怎么比,面试常考的分这几类:

相等性toBe===,只适合基本类型;toEqual 递归比较对象和数组每个属性,比对象首选它。两个高频坑:expect({a:1}).toBe({a:1}) 永远失败(引用不同);toEqual 会忽略 undefined 属性,需要严格比较用 toStrictEqualtoMatchObject 只匹配属性子集,适合只关心部分字段。

真假值toBeNull/toBeUndefined/toBeDefined 各自只匹配一个值;toBeTruthy/toBeFalsy 按 JS 强制布尔转换——0""nullundefinedNaN 是 falsy,其余 truthy。别混用:toBeFalsytoBeUndefined 宽泛得多。

数字toBeGreaterThan/toBeLessThan 及 OrEqual 变体。浮点数必须 toBeCloseTo——0.1 + 0.2 !== 0.3 是 JS 经典问题,用 toBe 比浮点数会翻车。

字符串与容器toMatch 匹配正则或子串;toContain 检查数组含元素或字符串含子串;toHaveLength 检查长度;toHaveProperty 检查对象属性。

异常toThrow 断言函数抛错,可匹配错误消息(字符串或正则)。必须传函数引用 expect(fn).toThrow(),传调用结果 expect(fn()).toThrow() 会在 expect 执行前就崩了。

异步resolves/rejects 断言 Promise 结果,必须 await——忘了 await 是新手最常犯的错,断言还没完成测试就静默通过了。

否定修饰:任何匹配器前加 .not 取反。但别滥用:expect(x).not.toBeUndefined() 不如直接 expect(x).toBeDefined()

MocktoHaveBeenCalledWith 检查调用参数;toHaveBeenCalledTimes 检查调用次数;toMatchSnapshot 做 UI 渲染快照回归。

追问

toBe 和 toEqual 有什么区别?什么时候用哪个?

toBe 是引用相等(===),基本类型值相同就过,对象必须同一引用才过。toEqual 递归比较每个属性,结构相同就过。一句话:基本类型用 toBe,对象数组用 toEqual。面试里 90% 的坑就是拿 toBe 比对象然后一脸懵。

Jest 异步测试怎么写?

三种方式:回调用 done 参数,Promise 用 resolves/rejects,async/await 同样配 resolves/rejects。最大坑是忘 await——expect(promise).resolves.toBe(x) 不加 await,断言没跑完测试就 passed 了。正确写法:await expect(fetchData()).resolves.toEqual(data)

toThrow 有什么注意点?

两个坑:一、必须传函数引用不是调用结果,前面说了;二、只捕获同步错误,异步错误得用 rejects.toThrow()。还有个细节:toThrow 匹配的是 error message 不是 error 类型,要精确匹配传字符串或正则。

.not 能和所有匹配器组合吗?

语法上可以,但语义上别乱用。expect(x).not.toBeUndefined()expect(x).toBeDefined() 结果一样,后者更清晰。.not 用在"不应该发生"的场景:函数不应抛错、返回不应为 null、mock 不应被调用。

项目里哪些匹配器用得最多?

toEqualtoBe 占七成以上——几乎所有测试都在比较值;toHaveBeenCalledWithtoThrow 是第二梯队——验证 mock 和错误分支;toMatchSnapshot 在组件测试中大量使用。掌握这几个就能覆盖日常 80% 的断言场景。

写段代码

javascript
// toBe vs toEqual expect(1 + 1).toBe(2); expect({ name: 'a' }).not.toBe({ name: 'a' }); // 引用不同,失败 expect({ name: 'a' }).toEqual({ name: 'a' }); // 深度相等,通过 // 异步断言必须 await await expect(api.getUser(1)).resolves.toEqual({ id: 1 }); // toThrow 传函数引用,匹配错误消息 expect(() => JSON.parse('invalid')).toThrow(); expect(() => risky()).toThrow(/permission denied/); // Mock 验证 expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2'); expect(mockFn).toHaveBeenCalledTimes(2);
标签:Jest