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

使用Mocha测试返回Promise的deferred.promise及Node.js Bot SDK代码问题

问题1:使用Mocha测试返回Promise的deferred.promise

Mocha对Promise的支持非常友好,根本不需要额外的复杂配置——你只需要让测试用例直接返回Promise,Mocha就会自动等待它完成(resolve或reject),不用手动调用done回调。我给你举几个实际的例子:

假设你有一个返回deferred.promise的函数,比如用Q库实现的延迟操作:

// 示例函数:返回deferred.promise
const Q = require('q');
function getDeferredData() {
  const deferred = Q.defer();
  setTimeout(() => {
    // 模拟成功返回数据
    deferred.resolve({ status: 'ok', data: ['room1', 'room2'] });
    // 模拟失败的情况可以用deferred.reject(new Error('获取数据失败'))
  }, 100);
  return deferred.promise;
}

对应的Mocha测试用例可以这么写:

const assert = require('assert');
const getDeferredData = require('./your-module');

describe('Deferred Promise 测试', () => {
  // 测试成功场景:直接返回Promise,用then断言结果
  it('应该成功返回会议室数据', () => {
    return getDeferredData().then(result => {
      assert.strictEqual(result.status, 'ok');
      assert.ok(Array.isArray(result.data));
    });
  });

  // 用async/await写法更简洁,可读性更高
  it('用async/await测试成功场景', async () => {
    const result = await getDeferredData();
    assert.strictEqual(result.status, 'ok');
    assert.deepStrictEqual(result.data, ['room1', 'room2']);
  });

  // 测试失败场景:返回Promise并在catch里断言错误
  it('应该捕获获取数据失败的错误', () => {
    return getFailedDeferredData().catch(error => {
      assert.strictEqual(error.message, '获取数据失败');
    });
  });
});

关键注意点:

  • 不要在返回Promise的测试里同时用done,否则可能导致测试超时或报错
  • 如果测试reject的情况,一定要确保错误被catch到,不然Mocha会把它当成测试失败
  • 优先用async/await写法,比嵌套then链清爽太多

问题2:resolveMeetingRoomFreeTime函数异常排查

先把你给出的代码片段补全(推测后面是then/catch链),方便分析:

resolveMeetingRoomFreeTime: function (session, args) {
  return new Promise(function (resolve, reject) {
    kgService.getFreeMeetingRooms(
      session.conversationData.floorEntityList,
      session.conversationData.roomEntityList,
      session.conversationData.meetingStartTimestamp,
      session.conversationData.meetingEndTimestamp,
      session.conversationData.meetingStartTime,
      session.conversationData.meetingEndTime,
      session.conversationData.meetingDuration
    )
    .then(freeRooms => resolve(freeRooms))
    .catch(error => reject(error));
  });
}

我给你列几个最可能的问题点和排查步骤:

1. 先排查参数合法性

session.conversationData里的参数很可能是undefined、null或者类型错误,比如floorEntityList不是数组,meetingStartTimestamp不是合法的时间戳。你可以在调用前加日志打印所有参数:

resolveMeetingRoomFreeTime: function (session, args) {
  // 先打印参数,排查是否有异常值
  console.log('传入getFreeMeetingRooms的参数:', {
    floorEntityList: session.conversationData.floorEntityList,
    roomEntityList: session.conversationData.roomEntityList,
    meetingStartTimestamp: session.conversationData.meetingStartTimestamp,
    meetingEndTimestamp: session.conversationData.meetingEndTimestamp,
    meetingStartTime: session.conversationData.meetingStartTime,
    meetingEndTime: session.conversationData.meetingEndTime,
    meetingDuration: session.conversationData.meetingDuration
  });

  return new Promise(function (resolve, reject) {
    // 原代码...
  });
}

2. 去掉多余的Promise嵌套(反模式)

你现在用new Promise包裹kgService.getFreeMeetingRooms的Promise完全没必要,属于Promise嵌套反模式,反而容易隐藏错误。直接返回kgService.getFreeMeetingRooms的Promise即可,还能简化代码:

resolveMeetingRoomFreeTime: function (session, args) {
  return kgService.getFreeMeetingRooms(
    session.conversationData.floorEntityList,
    session.conversationData.roomEntityList,
    session.conversationData.meetingStartTimestamp,
    session.conversationData.meetingEndTimestamp,
    session.conversationData.meetingStartTime,
    session.conversationData.meetingEndTime,
    session.conversationData.meetingDuration
  )
  .then(freeRooms => {
    // 这里可以加业务处理逻辑,比如过滤会议室
    return freeRooms.filter(room => room.capacity >= 10);
  })
  .catch(error => {
    // 在这里加错误日志,方便定位问题
    console.error('获取空闲会议室失败:', error.stack);
    // 重新抛出错误让上层调用者处理
    throw error;
  });
}

3. 单独测试kgService.getFreeMeetingRooms

问题可能出在kgService.getFreeMeetingRooms内部,比如它的参数校验严格、调用第三方接口失败、数据库查询错误等。你可以写个单独的测试用例,传入模拟的合法参数,看它是否能正常返回:

const assert = require('assert');
const kgService = require('./kgService');

describe('kgService.getFreeMeetingRooms', () => {
  it('传入合法参数应该返回空闲会议室列表', async () => {
    const mockParams = {
      floorEntityList: ['1F', '2F'],
      roomEntityList: ['大会议室', '小会议室'],
      meetingStartTimestamp: Date.now(),
      meetingEndTimestamp: Date.now() + 3600000, // 1小时后
      meetingStartTime: '09:00',
      meetingEndTime: '10:00',
      meetingDuration: 60
    };

    const result = await kgService.getFreeMeetingRooms(
      mockParams.floorEntityList,
      mockParams.roomEntityList,
      mockParams.meetingStartTimestamp,
      mockParams.meetingEndTimestamp,
      mockParams.meetingStartTime,
      mockParams.meetingEndTime,
      mockParams.meetingDuration
    );

    assert.ok(Array.isArray(result), '应该返回数组类型的结果');
    assert.ok(result.length >= 0, '结果长度应该大于等于0');
  });
});

4. 检查上层调用是否处理了错误

如果调用resolveMeetingRoomFreeTime的地方没有加catch,会导致Uncaught Promise Rejection,看起来像是函数内部异常。一定要确保上层调用有错误处理:

// 上层调用示例
resolveMeetingRoomFreeTime(session, args)
  .then(freeRooms => {
    session.send(`找到${freeRooms.length}个空闲会议室:${freeRooms.map(r => r.name).join(', ')}`);
  })
  .catch(error => {
    session.send('抱歉,获取会议室空闲时间失败,请稍后重试');
    console.error('上层捕获的错误:', error);
  });

内容的提问来源于stack exchange,提问作者Royjad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:56:35