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

如何编写Jest测试验证async-mutex的Mutex.acquire方法会阻塞代码执行?

async-mutex 二次acquire阻塞逻辑的正确测试方案

原有写法的问题

  1. 直接await第二次acquire时,由于第一个锁始终未释放,该异步调用会一直处于挂起状态,超过Jest默认5秒的异步回调超时阈值后,就会抛出你遇到的超时错误,根本无法执行后续的断言逻辑。
  2. expect(await mutex.acquire()).toThrow("Timeout")的写法不符合异步断言规范:await会优先等待Promise执行完成,若Promise rejected会直接抛出错误,不会进入后续的expect判断。正确的异步抛错断言需要使用.rejects匹配器。
  3. 你最初写法中的toStillBeRunningAfterSpecifiedSeconds不是Jest原生支持的匹配器,无法直接用来判断异步函数是否仍在运行。

正确实现方案

方案1:状态标记+延迟检测(无依赖库原生能力,纯验证阻塞逻辑)

核心思路是记录第二次acquire的完成状态,等待一段合理时间后验证该状态未变更,证明调用被阻塞:

it('should block second acquire call when mutex is locked', async () => {
  const mutex = new Mutex();
  const firstRelease = await mutex.acquire();
  expect(mutex.isLocked()).toBeTruthy();

  // 标记第二次acquire是否执行完成
  let isSecondAcquireDone = false;
  // 不直接await,先保存第二次acquire的Promise实例
  const secondAcquirePromise = mutex.acquire().then(() => {
    isSecondAcquireDone = true;
  });

  // 等待1秒(时间可自行调整,需远小于Jest默认5秒超时)
  await new Promise(resolve => setTimeout(resolve, 1000));

  // 状态仍为false,证明第二次acquire被阻塞未执行
  expect(isSecondAcquireDone).toBe(false);

  // 测试结束后释放锁,清理pending Promise,避免影响其他用例
  firstRelease();
  await secondAcquirePromise;
}, 10000); // 若调整了等待时间,可在此处单独设置当前用例的超时阈值,单位为毫秒

方案2:使用async-mutex自带超时参数(更简洁)

async-mutex的acquire方法支持传入第二个参数作为超时时间(单位毫秒),超过该时间未获取到锁会主动抛出超时错误,刚好可以用来验证阻塞逻辑:

it('should throw timeout error when second acquire exceeds wait time', async () => {
  const mutex = new Mutex();
  const release = await mutex.acquire();
  expect(mutex.isLocked()).toBeTruthy();

  // 第二次acquire设置1秒超时,拿不到锁会直接reject
  await expect(mutex.acquire(1000)).rejects.toThrow('Mutex timeout');

  // 释放锁清理资源
  release();
});

注意:不同版本的async-mutex超时错误提示可能存在差异,可根据实际运行的错误信息调整toThrow的匹配内容。

注意事项

  • 方案1的等待时间建议控制在3秒以内,避免触碰到Jest默认超时阈值,确有需要可在it的第三个参数单独指定当前用例的超时时间。
  • 无论用哪种方案,测试结束后都要主动释放持有的锁,避免残留的pending Promise影响其他测试用例的运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 21:15:09