使用Chai expect无法捕获Promise拒绝的问题排查
问题分析与解决方法
嘿,我来帮你搞定这个测试失败的问题,核心其实是两个容易忽略的关键点:
1. to.throw不适合测试Promise的异步错误
Chai的to.throw是专门给同步函数设计的,用来检测同步执行时抛出的异常。但你的tokenizer.tokenize返回的是Promise,异步的reject错误得用Chai的chai-as-promised插件来处理,它提供了专门针对Promise的断言方法。
2. 你的函数reject的是字符串,不是Error实例
测试提示Error: the string "Invalid value." was thrown, throw an Error :),说明你在函数里reject的是一个普通字符串(比如reject('Invalid value.')),但测试里写的to.throw(Error)期望的是抛出一个Error类的实例,两者类型不匹配,自然会失败。
具体解决步骤
第一步:安装并启用chai-as-promised插件
先安装依赖:
npm install chai-as-promised --save-dev
然后在你的测试文件顶部引入并启用它:
const chai = require('chai'); const chaiAsPromised = require('chai-as-promised'); // 启用Promise断言插件 chai.use(chaiAsPromised); const expect = chai.expect;
第二步:修改测试代码,适配Promise断言
接下来分两种情况处理:
情况一:推荐做法——让函数reject Error实例
先修改你的tokenize函数,把reject的字符串改成Error对象(这是更规范的错误处理方式):
// 原代码可能是这样的 reject('Invalid value.'); // 改成 reject(new Error('Invalid value.'));
然后测试代码改成用rejectedWith断言Error:
describe('fuzzing tokenization with 1000 invalid values', () => { it('should reject with an Error for invalid values', async () => { for(let i = 0; i <= 1000; i++){ const req = { body: { value: fuzzer.mutate.string('1000000000000000') }, user: { displayName: user } }; // 断言Promise会被Error实例拒绝,并且错误信息匹配 await expect(tokenizer.tokenize(req)).to.be.rejectedWith(Error, 'Invalid value.'); } }); });
情况二:暂时不想改函数,匹配拒绝的字符串
如果暂时没法修改tokenize函数,测试里直接匹配字符串即可:
describe('fuzzing tokenization with 1000 invalid values', () => { it('should reject with an error message for invalid values', async () => { for(let i = 0; i <= 1000; i++){ const req = { body: { value: fuzzer.mutate.string('1000000000000000') }, user: { displayName: user } }; // 断言Promise会被指定字符串拒绝 await expect(tokenizer.tokenize(req)).to.be.rejectedWith('Invalid value.'); } }); });
额外小提示
- 尽量用
let代替var,避免变量提升带来的意外问题 - 单测试用例里循环1000次可能会让测试变慢,你也可以考虑用Mocha的
it.each把每个模糊值拆成单独的测试用例,这样能更清晰地看到哪一次失败
内容的提问来源于stack exchange,提问作者Fede E.
相关产品推荐
相关产品推荐

