使用Jest和Enzyme测试React组件函数时遇问题求助
React组件测试问题:无法找到Header节点及带参数函数测试指南
第一个问题:为什么simulate报错找不到节点?
先看你的测试代码:
it("calls the `openPopup` function", () => { const onMockFunction = jest.fn(); const comp = shallow( <SparkTheme> <Contact handleButtonClick={onMockFunction} /> </SparkTheme> ); comp.find(Header).simulate("change"); expect(onMockFunction).toBeCalledTimes(1); });
问题出在shallow渲染的层级上:
shallow只会渲染最外层的组件(这里是SparkTheme),不会深入渲染它的子组件Contact,所以comp.find(Header)根本找不到任何节点,自然报错。- 你后来尝试用
dive()但失败,是因为如果SparkTheme是一个原生DOM组件(比如最终渲染成<div>),dive()只能用于自定义React组件,不能用于宿主组件(HTML原生标签),所以才会抛出TypeError: ShallowWrapper::dive() can not be called on Host Components。
解决方法
有两种可行的修复方式:
方式1:直接测试Contact组件(推荐,聚焦于目标组件)
如果SparkTheme只是全局样式或不需要在这个测试中验证,直接shallow渲染Contact即可:
it("calls the `openPopup` function when Header triggers the event", () => { const onMockFunction = jest.fn(); // 直接shallow渲染Contact,不需要外层的SparkTheme const comp = shallow(<Contact handleButtonClick={onMockFunction} />); // 现在能找到Header节点了,直接调用handleButtonClick comp.find(Header).prop("handleButtonClick")(); // 或者如果Header是通过某个事件触发的(比如按钮click),就simulate对应的事件 // comp.find(Header).simulate("click"); expect(onMockFunction).toBeCalledTimes(1); });
方式2:如果必须保留SparkTheme,使用mount渲染
mount会渲染整个组件树,包括所有子组件,这样就能找到Header了:
import { mount } from 'enzyme'; it("calls the `openPopup` function", () => { const onMockFunction = jest.fn(); const comp = mount( <SparkTheme> <Contact handleButtonClick={onMockFunction} /> </SparkTheme> ); // mount渲染后能找到Header comp.find(Header).prop("handleButtonClick")(); expect(onMockFunction).toBeCalledTimes(1); });
另外注意:你的测试里用了simulate("change"),但要确认Header组件内部是通过什么事件触发handleButtonClick的——如果是按钮的点击事件,应该用simulate("click"),否则事件不匹配也不会触发函数。
第二个问题:带参数的setValue函数如何测试?
你的思路是对的,只需要在simulate或者直接调用prop函数时传递模拟的event对象即可。
示例测试代码
假设setValue是通过Header里的输入框change事件触发的,测试可以这么写:
it("updates state when setValue is called", () => { const comp = shallow(<Contact />); // 模拟event对象 const mockEvent = { target: { value: "test value" } }; // 找到Header并触发change事件,传递mockEvent comp.find(Header).simulate("change", mockEvent); // 验证state是否更新 expect(comp.state("value")).toBe("test value"); });
或者直接调用prop函数(更直接,不需要依赖事件绑定):
it("updates state when setValue is called", () => { const comp = shallow(<Contact />); const mockEvent = { target: { value: "test value" } }; comp.find(Header).prop("setValue")(mockEvent); expect(comp.state("value")).toBe("test value"); });
额外提示:用debug()排查组件结构
你已经用了comp.debug(),这非常好!以后遇到找不到节点的问题,先打印debug()的输出,确认组件树的结构,再调整查找方式。比如你的debug输出里明确显示Contact组件内部有Header,那只要确保测试时能渲染到Contact的层级,就能找到Header了。
内容的提问来源于stack exchange,提问作者pranami
相关产品推荐
相关产品推荐

