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

如何用Vitest正确模拟node:crypto的randomUUID方法?

如何在Vitest中模拟node:crypto的randomUUID方法

场景说明

我需要测试一个调用node:crypto中randomUUID的简单函数,目标是把randomUUID模拟成固定返回值"123456789",被测函数代码如下:

import { randomUUID } from "node:crypto";

export function getRandomUUID(): string {
  return randomUUID();
}

尝试过的方案及问题

  • 参考某Stack Overflow帖子的方案,代码如下,但调用getRandomUUID返回undefined:
    vi.mock("node:crypto", async () => {
      const actual = await vi.importActual<typeof import("node:crypto")>("node:crypto");
      return {
        ...actual,
        randomUUID: vi.fn(() => "123456789"),
      };
    });
    
  • 参考Jest相关帖子的类似方案,Vitest抛出错误:

    Error: [vitest] No "default" export is defined on the "node:crypto" mock. Did you forget to return it from "vi.mock"?
    If you need to partially mock a module, you can use "importOriginal" helper inside:

    vi.mock(import("node:crypto"), async (importOriginal) => {
    const actual = await importOriginal()
    return {
    ...actual,
    // your mocked methods
    }
    })

  • 按提示修改后,出现类型错误Type 'string' is not assignable to type '${string}-${string}-${string}-${string}-${string}',且模拟仍然失败:
    vi.mock(import("node:crypto"), async (importOriginal) => {
      const actual = await importOriginal();
      return {
        actual,
        randomUUID: vi.fn(() => "123456789"),
      };
    });
    

正确解决方案

以下是可以正常工作的模拟代码,同时解决类型问题:

import { vi, describe, it, expect } from 'vitest';
import { getRandomUUID } from './path-to-your-function'; // 替换为实际文件路径

// 放在测试文件顶部,确保在导入被测函数前执行mock
vi.mock('node:crypto', async () => {
  // 保留模块其他未被模拟的功能
  const actual = await vi.importActual<typeof import('node:crypto')>('node:crypto');
  return {
    ...actual,
    // 用类型断言解决UUID类型约束问题
    randomUUID: vi.fn(() => '123456789' as `${string}-${string}-${string}-${string}-${string}`),
  };
});

describe('getRandomUUID', () => {
  it('返回模拟的固定UUID', () => {
    expect(getRandomUUID()).toBe('123456789');
    // 验证mock方法被调用
    expect(vi.mocked(require('node:crypto').randomUUID)).toHaveBeenCalled();
  });
});

关键要点

  1. 模块导入顺序:确保vi.mock放在测试文件最顶部,在导入被测函数之前执行,否则mock不会生效
  2. 正确展开模块导出:必须用...actual展开原模块的所有导出,而不是把actual作为对象属性返回(之前的错误写法就是这里出问题)
  3. 类型处理:TypeScript对randomUUID的返回值有严格的模板类型约束,需要用as ${string}-${string}-${string}-${string}-${string}``做类型断言,绕过类型检查

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:37:10