CRA下Jest mock React组件HOC时mockImplementation不生效
问题原因
两个核心问题导致mock不生效+报错:
- 你在
jest.mock工厂函数中定义的myHOC是普通箭头函数,不是Jest生成的mock spy函数,本身没有.mockImplementation方法,后续调用该方法无法替换实现,甚至可能因为函数调用返回异常值触发元素类型无效的报错。 - 测试文件顶部静态导入
Component时,组件模块会在第一时间完成加载,export default myHOC(Component)的逻辑在模块初始化阶段就已经执行完毕,此时拿到的是初始mock版本HOC包裹生成的组件。后续就算修改myHOC的实现,已经生成的包裹组件不会重新执行HOC逻辑,修改的配置自然不会生效。
实现方案
方案1:动态导入组件(无需修改业务组件代码)
核心逻辑是在每个测试用例修改完mock实现后,再动态导入组件,确保组件加载时使用的是当前用例配置的最新HOC mock实现。
import * as HOC from '../hoc/Component'; import { render } from '@testing-library/react'; import '@testing-library/jest-dom'; // 初始化mock时必须用jest.fn()包装myHOC,才能支持后续动态修改实现 jest.mock('../hoc/Component', () => ({ myHOC: jest.fn((C) => (props) => <C {...props} />) })); describe('Testing the Component', () => { // 每个用例执行前重置mock,避免用例之间相互污染 beforeEach(() => { HOC.myHOC.mockReset(); }); it('renders the component with first group of test props', async () => { const testSpecificProps = { // 对应第一组测试专用props }; // 配置当前用例的HOC mock实现 HOC.myHOC.mockImplementation((Comp) => (props) => <Comp {...testSpecificProps} {...props} />); // 动态导入组件,此时会用最新的mock实现包裹组件 const { default: Component } = await import('./Component'); const screen = render(<Component />); // 编写对应断言逻辑 }); it('renders the component with second group of test props', async () => { const testSpecificProps = { // 对应第二组测试专用props }; HOC.myHOC.mockImplementation((Comp) => (props) => <Comp {...testSpecificProps} {...props} />); const { default: Component } = await import('./Component'); const screen = render(<Component />); // 编写对应断言逻辑 }); });
方案2:导出原始未包裹组件(推荐,无mock负担)
这是单测场景下最稳定的方案,不需要处理复杂的mock逻辑,直接测试组件本身的逻辑:
首先修改组件文件,额外导出未被HOC包裹的原始组件:
import { myHOC } from '../hoc/Component'; // 命名导出原始组件,仅用于测试 export const Component = () => { // 组件原有逻辑 return ( // 原有JSX内容 ); }; // 默认导出保留HOC包裹后的版本,不影响业务代码使用 export default myHOC(Component);
测试文件直接导入原始组件,想传什么props直接传入即可,完全不需要mock HOC:
import { render } from '@testing-library/react'; import '@testing-library/jest-dom'; import { Component } from './Component'; describe('Testing the Component', () => { it('renders the component with first group of test props', () => { const testSpecificProps = { // 第一组测试props }; const screen = render(<Component {...testSpecificProps} />); // 编写断言 }); it('renders the component with second group of test props', () => { const testSpecificProps = { // 第二组测试props }; const screen = render(<Component {...testSpecificProps} />); // 编写断言 }); });
注意:如果选择方案2,只需要保证默认导出的HOC包裹组件在业务场景下正常工作即可,HOC本身的逻辑可以单独写测试用例覆盖,不需要和组件单测耦合。
内容的提问来源于stack exchange,提问作者dnarvaez27
相关产品推荐
相关产品推荐

