如何用Jest模拟带附加属性的组件?含单测试用例场景
解决Jest模拟带静态属性的组件问题
问题1:全局模拟时保留组件静态属性,仅修改渲染逻辑
直接用jest.mock时,要保留原组件的静态属性(比如SIZE),可以通过读取原模块的属性并赋值给模拟组件来实现:
// 在测试文件顶部全局模拟 jest.mock('@library', () => { // 导入原模块,避免完全替换所有导出 const originalModule = jest.requireActual('@library'); // 创建模拟Input组件,渲染为指定div const MockInput = jest.fn(() => <div data-testid="mock-input" />); // 复制原Input组件的所有静态属性(包括SIZE) MockInput.SIZE = originalModule.Input.SIZE; // 如果有其他静态属性,用Object.assign批量复制更高效 Object.assign(MockInput, originalModule.Input); return { ...originalModule, Input: MockInput }; });
这样模拟后,Input.SIZE.md等静态属性依然可用,同时组件会渲染成带有data-testid="mock-input"的div。
问题2:仅在单个测试用例中模拟组件
如果不想全局影响所有测试,可在目标测试用例内部临时模拟,有两种常用方式:
方式1:使用jest.doMock + 动态导入
test('仅当前测试模拟Input组件', () => { // 重置模块缓存,确保重新加载时使用新的模拟 jest.resetModules(); // 临时模拟@library模块 jest.doMock('@library', () => { const originalModule = jest.requireActual('@library'); const MockInput = jest.fn(() => <div data-testid="mock-input" />); MockInput.SIZE = originalModule.Input.SIZE; Object.assign(MockInput, originalModule.Input); return { ...originalModule, Input: MockInput }; }); // 必须在doMock之后动态导入App组件 const { default: App } = require('./App'); // 渲染并验证 render(<App />); expect(screen.getByTestId('mock-input')).toBeInTheDocument(); });
方式2:使用jest.spyOn临时替换
import { Input } from '@library'; import App from './App'; test('仅当前测试模拟Input组件', () => { // 保存原组件,测试后恢复 const originalInput = Input; // 创建带静态属性的模拟组件 const MockInput = jest.fn(() => <div data-testid="mock-input" />); MockInput.SIZE = Input.SIZE; Object.assign(MockInput, Input); // 替换@library的Input导出 const inputSpy = jest.spyOn(require('@library'), 'Input').mockImplementation(MockInput); // 渲染测试 render(<App />); expect(screen.getByTestId('mock-input')).toBeInTheDocument(); // 测试结束后恢复原组件,避免影响其他测试 inputSpy.mockRestore(); });
内容的提问来源于stack exchange,提问作者Jake Lam
相关产品推荐
相关产品推荐

