如何使用Enzyme测试依赖特定子组件类型的组件?
Enzyme测试Parent/Child组件场景问题
组件代码
class Parent extends React.Component { render() { let child; if(this.props.children[0].type.IS_CHILD){ this.props.children[0].isInsideParent = true; child = this.props.children[0]; return <div>{child}</div> } return <div>ERROR</div> } } class Child extends React.Component { public static IS_CHILD = true; render() { let parent; if(this.props.isInsideParent) return <div>OK</div>; return <div>ERROR</div> } }
测试场景问题
当使用Enzyme的不同渲染方式测试时:
const wrapper1 = shallow(<Parent><Child></Child></Parent>) const wrapper2 = shallow(<Parent><Child></Child></Parent>).dive(); const wrapper3 = mount(<Parent><Child></Child></Parent>)
只有mount能正常工作——因为它会完整渲染内部组件,此时children[0].type指向Child类,能读取到IS_CHILD静态属性。而shallow渲染时,Parent组件无法识别子元素类型:children[0].type会变成ShallowRenderStub,没有IS_CHILD属性,导致Parent返回ERROR。
现在需要解决:能否仅用Enzyme的shallow渲染完成这个场景的测试?
解决方案
方法1:手动给Shallow Stub添加静态属性
shallow渲染子组件时会生成Stub,我们可以手动给这个Stub的type添加IS_CHILD属性,让Parent的判断逻辑通过:
// 先shallow渲染Child得到Stub const childStub = shallow(<Child />).getElement(); // 给Stub的type添加静态属性 childStub.type.IS_CHILD = true; // 将处理后的Stub传入Parent const parentWrapper = shallow(<Parent>{childStub}</Parent>); // 验证结果 expect(parentWrapper.text()).not.toBe('ERROR'); expect(parentWrapper.find(Child).props().isInsideParent).toBe(true);
方法2:重构组件逻辑(推荐)
原组件中直接修改this.props.children的属性不符合React props不可变的设计原则,重构后不仅代码更规范,也能让测试更简单:
// 重构Parent组件,使用React.cloneElement传递props class Parent extends React.Component { render() { const [child] = this.props.children; if (child.type.IS_CHILD) { // 克隆子组件并传递isInsideParent属性,而非直接修改原props return <div>{React.cloneElement(child, { isInsideParent: true })}</div>; } return <div>ERROR</div>; } }
重构后,shallow测试可以直接验证子组件是否接收到正确的props:
const parentWrapper = shallow(<Parent><Child /></Parent>); expect(parentWrapper.find(Child).props().isInsideParent).toBe(true); expect(parentWrapper.find(Child).shallow().text()).toBe('OK');
方法3:直接调用组件的render方法
如果不想修改组件代码,也可以直接调用Parent的render方法,手动传入带有正确type的子元素:
const childElement = <Child />; // 构造Parent实例并调用render方法 const parentInstance = shallow(<Parent>{childElement}</Parent>).instance(); const renderedResult = shallow(parentInstance.render()); expect(renderedResult.text()).not.toBe('ERROR');
内容的提问来源于stack exchange,提问作者igol
相关产品推荐
相关产品推荐

