Jest.js中如何在未按预期抛出错误时判定测试用例失败
问题场景
你正在为Feathers.js/Node.js API补充测试提升分支/函数覆盖率,测试框架选用Jest。当前某服务存在一个带取值约束的属性,对应校验逻辑暂未实现:
- 合法取值范围:
const validValues = ["System", "Engineering", "Production"]
- 非法取值示例:
const invalidValues = ["Some", "Invalid", "Value"]
预期逻辑为:传入合法值时API正常接收请求并返回有效响应;传入非法值时API直接拒绝请求。
你计划先编写测试用例,实现“API接收非法值(未抛出预期错误)时测试直接失败”的效果,倒逼校验逻辑补全,但当前编写的测试代码无法达到这个判定效果。
你当前的测试代码如下:
it("test service for invalid values", async () => { const invalidValues = ["Some", "Invalid", "Value"]; invalidValues.map(async (invalidValue) => { await expect(async () => { await app.service("release-types").create({ someProperty: "some Value" propertyWithValueConstraint: invalidValue, }); }).rejects.toThrow(); }); });
原有代码的核心问题
- 用
Array.map遍历执行异步断言时,没有等待map返回的Promise数组执行完成。Jest会在测试函数同步代码执行完后直接结束用例,根本不会等内部的异步请求和断言执行,就算服务没抛错,测试也会误判为通过,出现假阳性结果。 expect的rejects断言写法冗余,不需要额外包裹一层async函数,直接传入返回Promise的服务调用即可。- 缺少合法值的对照用例,无法覆盖“接口无论传什么值都抛错”的反向异常场景。
正确实现方案
推荐用for...of循环逐个执行异步断言,保证Jest能等待所有校验逻辑执行完成,代码如下:
it("should reject requests with invalid property values", async () => { const invalidValues = ["Some", "Invalid", "Value"]; // 用for...of替代map,逐个等待异步断言执行 for (const invalidValue of invalidValues) { await expect( app.service("release-types").create({ someProperty: "some Value", propertyWithValueConstraint: invalidValue, }) ).rejects.toThrow(); } }); // 补充合法值对照用例,避免校验逻辑写死全量拦截 it("should accept requests with valid property values", async () => { const validValues = ["System", "Engineering", "Production"]; for (const validValue of validValues) { await expect( app.service("release-types").create({ someProperty: "some Value", propertyWithValueConstraint: validValue, }) ).resolves.not.toThrow(); } });
如果你想并行执行所有非法值校验,也可以用Promise.all包裹map返回的Promise数组,效果一致:
it("test service for invalid values", async () => { const invalidValues = ["Some", "Invalid", "Value"]; await Promise.all( invalidValues.map(async (invalidValue) => { await expect( app.service("release-types").create({ someProperty: "some Value", propertyWithValueConstraint: invalidValue, }) ).rejects.toThrow(); }) ); });
效果说明
只要校验逻辑没实现,服务接收非法值后没有抛出错误,rejects.toThrow()断言就会直接判定失败,完全符合你“校验逻辑缺失时测试挂掉”的需求。后续补全校验后,你还可以把toThrow()替换为更精准的断言,比如指定错误类型、匹配错误提示文本,进一步提升测试严谨性。
内容的提问来源于stack exchange,提问作者ix.trc
相关产品推荐
相关产品推荐

