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

Jest无法识别Spy已调用的技术问题求助

解决Jest中Promise回调里Spy函数未被正确断言的问题

你遇到的核心问题是Jest在异步代码(Promise的then回调)执行完成前就跑完了断言。sendSpy是同步触发的,所以它的断言能顺利通过;但sendCallbackSpy是在Promise的微任务队列里执行的,测试函数同步执行完所有断言后,微任务才会被处理——此时断言已经结束,自然会判定sendCallbackSpy未被调用。

常见解决方案(附代码示例)

假设你的业务代码大致是这样的:

// 业务代码示例
const sendSpy = jest.fn(() => Promise.resolve('success'));
const sendCallbackSpy = jest.fn();

function executeTask() {
  sendSpy().then(() => {
    sendCallbackSpy(); // 这个Spy在测试里没被断言到
  });
}

方法1:让测试函数返回Promise

直接返回包含断言的Promise,Jest会自动等待这个Promise完成后再结束测试:

test('should trigger sendCallbackSpy after sendSpy resolves', () => {
  executeTask();
  expect(sendSpy).toHaveBeenCalled();
  
  // 返回Promise,等待sendSpy的异步操作完成后再断言
  return sendSpy.mock.results[0].value.then(() => {
    expect(sendCallbackSpy).toHaveBeenCalled();
  });
});

方法2:使用async/await(最简洁推荐)

如果可以修改业务函数让它返回内部的Promise,直接await即可:

// 先修改业务函数,返回Promise
function executeTask() {
  return sendSpy().then(() => {
    sendCallbackSpy();
  });
}

// 测试用例
test('should trigger sendCallbackSpy after sendSpy resolves', async () => {
  await executeTask();
  
  expect(sendSpy).toHaveBeenCalled();
  expect(sendCallbackSpy).toHaveBeenCalled();
});

如果不能修改业务函数,也可以直接await Spy返回的Promise:

test('should trigger sendCallbackSpy after sendSpy resolves', async () => {
  executeTask();
  expect(sendSpy).toHaveBeenCalled();
  
  await sendSpy.mock.results[0].value; // 等待Promise完成
  expect(sendCallbackSpy).toHaveBeenCalled();
});

方法3:使用Jest的done回调

通过done参数手动告诉Jest什么时候结束测试:

test('should trigger sendCallbackSpy after sendSpy resolves', (done) => {
  executeTask();
  expect(sendSpy).toHaveBeenCalled();
  
  // 监听sendCallbackSpy的调用,一旦触发就完成测试
  sendCallbackSpy.mockImplementation(() => {
    expect(sendCallbackSpy).toHaveBeenCalled();
    done();
  });
  
  // 别忘了捕获Promise错误,避免测试超时
  sendSpy.mock.results[0].value.catch(done);
});

关于添加console.log后“看似正常”的说明

你提到加了console.log后情况有变化,这只是偶然的伪修复:console.log是同步操作,它会占用一点执行时间,让事件循环有机会提前处理微任务(也就是then回调),但这种方式完全不可靠,不能作为正式解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:41:54