如何在Enzyme中模拟React组件内部函数返回值以测试三元表达式
这问题我之前在项目里碰过好多次,其实分类组件和函数组件两种场景来处理就行,我给你一步步拆解清楚:
1. 类组件中的非props函数模拟
假设你的类组件长这样,内部有个checkCondition非props函数控制三元渲染:
class MyComponent extends React.Component { // 内部非props函数 checkCondition() { return this.props.someValue > 10; } render() { return <div>{this.checkCondition() ? '显示内容A' : '显示内容B'}</div>; } }
你可以通过Enzyme的instance()方法拿到组件实例,再用Jest的jest.fn()来mock这个函数,步骤如下:
import { shallow } from 'enzyme'; import MyComponent from './MyComponent'; test('模拟内部函数测试三元表达式逻辑', () => { // 浅渲染组件 const wrapper = shallow(<MyComponent />); // 获取组件实例,替换内部函数为mock函数并返回true wrapper.instance().checkCondition = jest.fn(() => true); // 关键:强制组件重新渲染,让mock生效 wrapper.update(); // 断言此时显示内容A expect(wrapper.text()).toBe('显示内容A'); // 切换mock返回值为false,再次测试 wrapper.instance().checkCondition.mockReturnValue(false); wrapper.update(); expect(wrapper.text()).toBe('显示内容B'); });
特殊情况:箭头函数定义的类方法
如果你的内部函数是用箭头函数定义的(比如checkCondition = () => {}),它属于实例属性,挂载后再mock可能不生效,需要在渲染时提前注入mock:
test('模拟箭头函数类方法', () => { const mockCheckCondition = jest.fn(() => true); // 渲染时直接替换实例上的方法 const wrapper = shallow(<MyComponent />, { instance: { checkCondition: mockCheckCondition } }); expect(wrapper.text()).toBe('显示内容A'); // 直接修改mock返回值,更新组件 mockCheckCondition.mockReturnValue(false); wrapper.update(); expect(wrapper.text()).toBe('显示内容B'); });
2. 函数组件中的非props函数模拟
函数组件没有实例,内部普通函数没法直接通过Enzyme获取,所以更推荐的做法是把内部逻辑提取到组件外部,方便mock:
// 把需要mock的函数提取到组件外,单独导出 export function checkCondition() { return Math.random() > 0.5; } function MyFunctionalComponent() { return <div>{checkCondition() ? '内容A' : '内容B'}</div>; }
然后测试时用jest.spyOn来mock这个外部函数:
import { shallow } from 'enzyme'; import MyFunctionalComponent, { checkCondition } from './MyFunctionalComponent'; test('模拟外部函数测试函数组件', () => { // spyOn目标模块的checkCondition函数,替换为mock const mockCheck = jest.spyOn(require('./MyFunctionalComponent'), 'checkCondition'); // 设置mock返回true mockCheck.mockReturnValue(true); const wrapper = shallow(<MyFunctionalComponent />); expect(wrapper.text()).toBe('内容A'); // 切换返回值为false mockCheck.mockReturnValue(false); wrapper.update(); expect(wrapper.text()).toBe('内容B'); // 测试结束后清理mock,避免影响其他用例 mockCheck.mockRestore(); });
小提示
- 不管哪种组件,mock函数后一定要调用
wrapper.update()触发重新渲染,否则组件不会更新视图。 - 测试完成后记得清理mock(比如
mockRestore()),防止mock污染其他测试用例。
内容的提问来源于stack exchange,提问作者The Walrus
相关产品推荐
相关产品推荐

