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

Jest测试window.crypto密码生成函数时无法生成有效值的问题

问题分析与解决方案

问题根源

你的测试代码中对window.crypto.getRandomValues的mock逻辑错误:

  • getRandomValues的原生行为是修改传入的TypedArray对象,填充随机值,而非返回新的数组。
  • 你用mockReturnValueOnce(new Uint32Array(20))返回新数组,但原函数里的values是自己创建的空数组,mock的返回值不会被使用,导致values始终是全0的状态。
  • 全0对应charset的第一个字符'A',生成的AAAAAAAAAAAAAAAAAAAA不满足正则要求,触发无限递归。

修复后的测试代码

修改mock逻辑,让它正确修改传入的数组,同时确保生成的密码满足正则(避免递归):

it('should generate a x length password', () => {
  const mGetRandomValues = jest.fn((array: Uint32Array) => {
    // 填充数值,确保生成的密码包含大写字母、数字、特殊符号
    // 索引对应charset里的字符区间:0-25=大写,52-61=数字,62+=特殊符号
    array.set([
      0,    // 'A'(大写)
      52,   // '0'(数字)
      62,   // '~'(特殊符号)
      ...Array(array.length - 3).fill(10) // 其余位置填充固定索引简化测试
    ]);
    return array; // getRandomValues会返回传入的原数组
  });

  Object.defineProperty(globalThis, 'crypto', {
    value: { getRandomValues: mGetRandomValues },
  });

  const passwordLength = 20;
  const generatedPwd = utils.genPwd(passwordLength);

  // 验证密码长度
  expect(generatedPwd).toHaveLength(passwordLength);
  // 验证getRandomValues被正确调用
  expect(mGetRandomValues).toHaveBeenCalledTimes(1);
  const callArg = mGetRandomValues.mock.calls[0][0];
  expect(callArg).toBeInstanceOf(Uint32Array);
  expect(callArg.length).toBe(passwordLength);
  // 可选:验证密码符合正则规则
  expect(generatedPwd).toMatch(/^(?=.*[A-Z])(?=.*[!@#$%^&*])(?=.*[0-9]).{8,}$/);
});

额外优化建议

  1. 避免无限递归风险:原密码生成函数如果极端情况下一直生成不满足正则的字符串,会触发栈溢出。可以添加递归次数上限:
const genPwd = (length: number, attempts = 0): string => {
  const maxAttempts = 10;
  if (attempts >= maxAttempts) {
    throw new Error('Failed to generate valid password after max attempts');
  }
  // ...原有逻辑
  if (!regex.test(result)) {
    return genPwd(length, attempts + 1);
  }
  // ...
};
  1. 更精准的mock匹配:原测试中toBeCalledWith(new Uint32Array(20))会失败,因为每次创建的Uint32Array是不同的对象。改用expect.any(Uint32Array)或检查实例类型+长度更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 12:35:29