js单元测试中应mock web crypto api而非真实调用,推荐用jest.mock/vi.mock拦截crypto.subtle方法并返回预设值,同时封装crypto调用为可注入函数以确保类型一致和环境兼容。

在 JS 单元测试中,不建议真正调用 Web Crypto API 来生成密钥或加密结果,因为它的行为依赖环境(如浏览器/Node.js)、异步、有侧信道风险,且输出不可控。正确做法是 **Mock 其返回值**,让测试聚焦于业务逻辑而非密码学实现。
直接替换全局 crypto 子模块(推荐)
Web Crypto API 主要通过 window.crypto.subtle 提供方法(如 encrypt、generateKey、digest)。可在测试前用 Jest 或 Vitest 的 jest.mock / vi.mock 拦截并返回预设结果:
- 对
generateKey,返回一个带publicKey/privateKey属性的模拟对象(不必真实有效,只要结构匹配) - 对
encrypt,返回固定字节数组(如new Uint8Array([1, 2, 3, 4])),确保每次测试一致 - 对
digest,返回已知哈希值的Uint8Array(如 SHA-256 的 "hello" → 以 hex 表示的 32 字节)
用工厂函数封装 crypto 调用,便于注入 mock
避免在业务代码中硬写 crypto.subtle.encrypt(...)。改用可注入的工具函数:
数字货币行情监控工具。当用户询问「比特币」「以太坊」「BTC」「ETH」「数字货币行情」「加密货币」「Crypto」「比特币价格」「以太坊价格」时使用。数据来源:Yahoo Finance(实时价格)和 CoinGecko(市值/交易量)。📢微信公众号:PM熊叔
export async function encryptWithAES(key, data, iv) {
return crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, data);
}
测试时传入自定义实现:
// test.jsimport { encryptWithAES } from './cryptoService.js';
import { vi } from 'vitest';
vi.mock('./cryptoService.js', async (importOriginal) => {
const mod = await importOriginal();
return {
...mod,
encryptWithAES: vi.fn().mockResolvedValue(new Uint8Array([0x9f, 0x3a, 0x1c]))
};
});
注意兼容性与类型一致性
Mock 返回值必须符合原生 API 的类型约定,否则业务代码可能报错:
- 所有方法返回
Promise,不能直接返回普通值 - 密钥对象需含
type、extractable、algorithm等字段(即使 mock 只填占位符) - 加密/解密结果必须是
ArrayBuffer或Uint8Array,不能是字符串或 hex - Node.js 环境需额外 mock
globalThis.crypto(Jest 默认不提供)
不推荐:Patch window.crypto.subtle
虽然可以手动赋值 window.crypto.subtle = { encrypt: jest.fn(...) },但容易遗漏方法、破坏原有属性(如 sign、verify),且在多测试文件间产生污染。优先使用模块级 mock 或依赖注入。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










