如何测试React组件并Mock crypto.subtle.digest(Vitest+RTL)
测试React组件函数并Mock crypto.subtle.digest(Vitest + React Testing Library)
问题背景
我需要了解如何测试React组件中的函数,以及如何Mock组件中使用的crypto.subtle.digest方法,当前使用的测试工具是Vitest和React Testing Library。运行测试时出现以下错误:
TypeError: Cannot read properties of undefined (reading 'digest') ❯ Module.bgColorByEmail src/utils/bgColorByEmail.ts:4:36 2| const encoder = new TextEncoder(); 3| const data = encoder.encode(email); 4| const hash = await crypto.subtle.digest('SHA-384', data); | ^ 5| const hashArray = Array.from(new Uint8Array(hash)); 6| const hashHex = hashArray ❯ setColor src/features/user/AboutUser/AboutUser.tsx:36:27 ❯ src/features/user/AboutUser/AboutUser.tsx:39:5 ❯ commitHookEffectListMount node_modules/react-dom/cjs/react-dom.development.js:23150:26 ❯ commitPassiveMountOnFiber node_modules/react-dom/cjs/react-dom.development.js:24931:11 ❯ commitPassiveMountEffects_complete node_modules/react-dom/cjs/react-dom.development.js:24891:9 ❯ commitPassiveMountEffects_begin node_modules/react-dom/cjs/react-dom.development.js:24878:7 ❯ commitPassiveMountEffects node_modules/react-dom/cjs/react-dom.development.js:24866:3 ❯ flushPassiveEffectsImpl node_modules/react-dom/cjs/react-dom.development.js:27039:3 ❯ flushPassiveEffects node_modules/react-dom/cjs/react-dom.development.js:26984:14 This error originated in "src/__tests__/AboutUser.test.tsx" test file. It doesn't mean the error was thrown inside the file itself, but while it was running. The latest test that might've caused the error is "update user form must be in the document". It might mean one of the following: - The error was thrown, while Vitest was running this test. - This was the last recorded test before the error was thrown, if error originated after test finished its execution.
我尝试了以下Mock代码,但未解决问题:
vi.mock('crypto.subtle.decrypt', async () => { return { ...vi.importMock('bgColorByEmail'), crypto: vi.fn(), }; });
解决方案
1. 正确Mock crypto.subtle.digest
之前的Mock无效是因为目标对象错误,且没有正确构建crypto.subtle的层级结构。直接在全局对象上Mock即可:
在测试文件顶部或者项目的setupTests.ts中添加全局Mock:
// 全局Mock crypto对象及subtle.digest方法 global.crypto = { subtle: { digest: vi.fn().mockResolvedValue(new Uint8Array([1, 2, 3])) // 返回模拟的哈希值 } } as unknown as Crypto;
如果需要给不同测试用例设置不同返回值,可在对应用例中动态修改:
test('测试组件渲染逻辑', async () => { // 为当前测试用例单独设置返回值 crypto.subtle.digest.mockResolvedValueOnce(new Uint8Array([4, 5, 6])); render(<AboutUser />); // 后续断言操作 });
2. 单独测试工具函数
如果要测试bgColorByEmail这类工具函数,直接导入后编写测试即可:
import { bgColorByEmail } from '../src/utils/bgColorByEmail'; test('bgColorByEmail 根据邮箱生成正确颜色', async () => { // Mock digest返回特定值 crypto.subtle.digest.mockResolvedValue(new Uint8Array([0, 0, 255])); const color = await bgColorByEmail('test@example.com'); expect(color).toBe('#0000ff'); // 根据实际逻辑修改断言内容 });
3. 组件测试注意事项
测试依赖该工具函数的组件时,要确保渲染前已完成Mock,同时处理异步逻辑避免测试不稳定:
import { render, screen } from '@testing-library/react'; import AboutUser from '../src/features/user/AboutUser/AboutUser'; beforeEach(() => { // 重置mock状态,避免用例间污染 crypto.subtle.digest.mockReset(); // 设置默认返回值 crypto.subtle.digest.mockResolvedValue(new Uint8Array([100, 100, 100])); }); test('update user form must be in the document', async () => { render(<AboutUser />); // 等待异步效果完成 await screen.findByText('更新用户'); // 替换为组件中的实际文本 expect(screen.getByRole('form')).toBeInTheDocument(); });
内容的提问来源于stack exchange,提问作者Дмитрий Волченко
相关产品推荐
相关产品推荐

