You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:46:23