使用hapijs/lab测试报错:done is not a function问题求助
解决Hapi Lab测试中"done is not a function"的问题
我最近在给Hapi服务器写测试用例的时候踩了个一模一样的坑——用了一段Lab相关的示例代码,结果运行时一直弹出done is not a function的错误,我的代码大概是这样的:
const Code = require('code'); const Lab = require('lab'); const lab = exports.lab = Lab.script(); lab.test('expect an error from a promise', (done) => { return new Promise((resolve, reject) => { try { resolve(2); } catch (err) { reject(err); } }).then((result) => { console.log('5) resolved'); done(new Error('promise should...');
问题根源
其实这个错误的核心原因很简单:Lab的测试函数不允许同时使用done回调和返回Promise。这两种是Lab处理异步测试的互斥方式——要么通过done回调手动通知测试结束,要么返回Promise让Lab自动监听异步流程,同时用就会导致done参数被忽略,自然就不是一个函数了。
另外你的代码还有个小语法问题:done(new Error('promise should...');少了一个闭合的括号,不过这不是触发当前错误的主要原因。
解决方案
这里给你两种可行的修复方式,按需选择:
方案1:纯Promise写法(推荐)
既然已经用了Promise,那就直接去掉done参数,在Promise链里用Code.expect做断言——只要断言失败,就会自动抛出错误,Lab会捕获这个错误并标记测试失败:
const Code = require('code'); const Lab = require('lab'); const lab = exports.lab = Lab.script(); const expect = Code.expect; lab.test('expect an error from a promise', () => { return new Promise((resolve, reject) => { resolve(2); // 这里故意resolve,用来触发断言失败 }).then((result) => { console.log('5) resolved'); // 断言结果不符合预期,会自动抛出错误 expect(result).to.be.a.string(); }); });
如果是要测试Promise被reject的场景,用async/await配合断言会更清晰:
lab.test('expect a promise to reject', async () => { const testPromise = new Promise((resolve, reject) => { reject(new Error('expected failure')); }); // 验证Promise是否按预期reject await expect(testPromise).to.reject(Error, 'expected failure'); });
方案2:纯done回调写法
如果一定要用done回调,那就要去掉Promise的返回,在Promise的then/catch里手动调用done,同时要把所有可能的错误传递给它:
const Code = require('code'); const Lab = require('lab'); const lab = exports.lab = Lab.script(); const expect = Code.expect; lab.test('expect an error from a promise', (done) => { new Promise((resolve, reject) => { resolve(2); }).then((result) => { console.log('5) resolved'); try { expect(result).to.be.a.string(); done(); // 断言成功,通知测试结束 } catch (err) { done(err); // 断言失败,把错误传给Lab } }).catch(done); // 捕获Promise本身reject的错误 });
这种方式要注意:必须确保所有分支都调用done,不然测试会因为超时而失败。
内容的提问来源于stack exchange,提问作者Jean
相关产品推荐
相关产品推荐

