如何用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(); }); });
关键要点
- 模块导入顺序:确保
vi.mock放在测试文件最顶部,在导入被测函数之前执行,否则mock不会生效 - 正确展开模块导出:必须用
...actual展开原模块的所有导出,而不是把actual作为对象属性返回(之前的错误写法就是这里出问题) - 类型处理:TypeScript对
randomUUID的返回值有严格的模板类型约束,需要用as${string}-${string}-${string}-${string}-${string}``做类型断言,绕过类型检查
内容的提问来源于stack exchange,提问作者Alberto
相关产品推荐
相关产品推荐

