Enzyme shallow快照测试如何忽略子组件仅捕获顶层组件信息
问题根因
你对shallow渲染的作用存在误解:调用shallow(<MyComponent />)时,仅会跳过渲染MyComponent本身的子组件内部实现,但是MyComponent返回的JSX结构里的所有嵌套元素(包括BackgroundComponent、MidComponent、InnerComponent的层级结构)都会被完整保留下来,你对find到的组件元素直接拍快照,自然会带上所有嵌套的子元素内容。
可行解决方案
下面提供3种可落地的方案,你可以根据自己的需求选择:
方案1:单独为每个组件编写独立快照测试
最合理的方案是将三个组件的测试用例拆分,每个组件单独做shallow渲染,完全和上层组件解耦:
// BackgroundComponent.test.js import React from 'react'; import { shallow } from 'enzyme'; import BackgroundComponent from './BackgroundComponent'; it('BackgroundComponent 快照符合预期', () => { // 仅传入该组件需要的props,children可以传空值或者模拟占位 expect(shallow(<BackgroundComponent customProp="test">{null}</BackgroundComponent>)).toMatchSnapshot(); });
// MidComponent.test.js import React from 'react'; import { shallow } from 'enzyme'; import MidComponent from './MidComponent'; it('MidComponent 快照符合预期', () => { expect(shallow(<MidComponent>{null}</MidComponent>)).toMatchSnapshot(); });
// InnerComponent.test.js import React from 'react'; import { shallow } from 'enzyme'; import InnerComponent from './InnerComponent'; it('InnerComponent 快照符合预期', () => { expect(shallow(<InnerComponent>Some text value</InnerComponent>)).toMatchSnapshot(); });
这种方案生成的快照完全只包含当前组件的内容,体积最小,也方便后续组件单独迭代时维护测试。
方案2:mock下层子组件实现
如果你坚持要在MyComponent的测试文件里生成三个组件的快照,可以用jest.mock将下层子组件替换为简单的占位组件,避免真实子组件的内容被打进快照:
import React from 'react'; import { shallow } from 'enzyme'; import MyComponent from '../../src/components/MyComponent'; // mock下层组件,替换为无内容的占位元素 jest.mock('../../src/components/MidComponent', () => () => <span data-testid="mid-component-placeholder" />); jest.mock('../../src/components/InnerComponent', () => () => <span data-testid="inner-component-placeholder" />); describe('MyComponent tests', () => { const render = props => shallow(<MyComponent/>); it('生成三个独立快照', () => { const wrapper = render(); // 快照仅包含BackgroundComponent自身属性 + 占位的MidComponent expect(wrapper.find('BackgroundComponent')).toMatchSnapshot('BackgroundComponent 快照'); // 快照仅包含MidComponent自身属性 + 占位的InnerComponent expect(wrapper.find('MidComponent')).toMatchSnapshot('MidComponent 快照'); // 快照仅包含InnerComponent自身属性 expect(wrapper.find('InnerComponent')).toMatchSnapshot('InnerComponent 快照'); }); });
方案3:自定义快照比对内容
如果你不想拆分测试也不想mock组件,可以手动提取组件的属性生成快照,主动排除children字段:
it('生成三个独立快照', () => { const wrapper = render(); const bgComp = wrapper.find('BackgroundComponent'); // 仅保留组件类型和自身props,排除children expect({ type: bgComp.type(), props: Object.fromEntries(Object.entries(bgComp.props()).filter(([key]) => key !== 'children')) }).toMatchSnapshot('BackgroundComponent 快照'); const midComp = wrapper.find('MidComponent'); expect({ type: midComp.type(), props: Object.fromEntries(Object.entries(midComp.props()).filter(([key]) => key !== 'children')) }).toMatchSnapshot('MidComponent 快照'); expect(wrapper.find('InnerComponent')).toMatchSnapshot('InnerComponent 快照'); });
内容的提问来源于stack exchange,提问作者karvai
相关产品推荐
相关产品推荐

