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

如何在Mocha中测试未被await的异步函数调用?

如何测试异步postReservation服务是否被调用?

你当前依赖固定时长等待的测试方案既不可靠(异步操作耗时可能波动),又会拖慢测试执行速度。更优的方案是使用**测试替身(Mock)**跟踪postReservation的调用状态,完全不需要等待。

业务代码参考

bookReservation函数

async function bookReservation(...)
{
    await bookReservationForUser(...);
    postReservation(...); // 注意:此处未使用await,若需确保postReservation执行完成,建议添加await
}

postReservation函数

async function postReservation(...)
{
    await DoSomeThing();
    await DoSomeOtherThing();
}

优化后的测试方案

方案1:使用Sinon.js创建Mock(推荐)

Sinon.js是Mocha生态中常用的测试替身库,能方便跟踪函数调用:

  1. 安装依赖:
npm install sinon chai --save-dev
  1. 编写测试代码:
const sinon = require('sinon');
const { expect } = require('chai');
const { bookReservation, postReservation } = require('./your-service-module'); // 替换为实际模块路径

describe('预订服务测试套件', function() {
  it('调用bookReservation时应触发postReservation', async function() {
    // 创建postReservation的mock实例,期望被调用一次
    const postReservationMock = sinon.mock(postReservation);
    postReservationMock.expects('call').once();

    // 执行待测试函数
    await bookReservation(...); // 传入测试所需参数

    // 验证mock是否符合预期
    postReservationMock.verify();
    // 恢复原函数,避免影响其他测试
    postReservationMock.restore();
  });
});

方案2:手动Mock函数(无第三方依赖)

如果不想引入额外库,可以手动替换postReservation为跟踪调用状态的函数:

const { expect } = require('chai');
const { bookReservation, postReservation } = require('./your-service-module');

describe('预订服务测试套件', function() {
  let originalPostReservation;
  let isPostReservationCalled = false;

  // 每个测试前保存原函数并替换为mock
  beforeEach(function() {
    originalPostReservation = postReservation;
    isPostReservationCalled = false;
    global.postReservation = (...args) => {
      isPostReservationCalled = true;
      // 可选:若需要保留原函数的异步逻辑,返回原函数执行结果
      return originalPostReservation(...args);
    };
  });

  // 每个测试后恢复原函数
  afterEach(function() {
    global.postReservation = originalPostReservation;
  });

  it('调用bookReservation时应触发postReservation', async function() {
    await bookReservation(...);
    expect(isPostReservationCalled).to.be.true;
  });
});

额外提示

如果业务逻辑需要确保postReservation执行完成后bookReservation才返回,建议在bookReservation中给postReservation添加await:

async function bookReservation(...)
{
    await bookReservationForUser(...);
    await postReservation(...); // 添加await确保异步操作完成
}

这种情况下,测试时依然不需要额外等待,直接断言mock的调用状态即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:09:23