如何使用Enzyme测试Ant Design包裹的表单?
解决Ant Design表单按钮点击测试不触发函数的问题
我之前也踩过这个坑,主要是Ant Design的Form.create()高阶组件特性,加上Enzyme shallow渲染的限制导致的,咱们一步步来解决:
问题根源
- Shallow渲染的局限性:
Form.create()会生成一个高阶组件,shallow渲染只会停留在这个高阶组件层面,没法深入到你的SignInForm内部找到按钮元素,所以wrapper.find("#button-id")其实根本没定位到目标按钮。 - 提交按钮的触发逻辑:如果你的按钮是表单提交按钮(设置了
htmlType="submit"),它的点击实际是触发表单的onSubmit事件,而不是直接绑定你的newFunction,直接模拟click自然不会生效。
方案一:使用mount渲染并模拟正确事件
把shallow换成mount,它会完整渲染整个组件树,这样就能找到内部的按钮或表单元素:
import React from 'react'; import { mount } from 'enzyme'; import { SignInForm } from './SignInForm'; import { Form } from 'antd'; test("should call newFunction on button click", () => { const newFunction = jest.fn(); const WrappedForm = Form.create()(SignInForm); const wrapper = mount(<WrappedForm newFunction={newFunction} />); // 如果按钮直接绑定onClick,直接模拟点击 wrapper.find("#button-id").simulate("click"); // 如果按钮是表单提交按钮,更准确的是模拟表单提交 // wrapper.find(Form).simulate('submit'); expect(newFunction).toHaveBeenCalled(); });
方案二:直接测试未被包装的原始组件
既然Form.create()是高阶组件,我们可以绕过它,直接测试你的SignInForm原始组件,只需要mock Form注入的form props即可,这样用shallow也能正常工作:
import React from 'react'; import { shallow } from 'enzyme'; import { SignInForm } from './SignInForm'; test("should call newFunction on button click", () => { const newFunction = jest.fn(); // mock Form.create注入的form对象,只保留组件需要的方法 const mockForm = { getFieldDecorator: jest.fn((field, opts) => (child) => child), // 如果组件用到了validateFields,也需要mock validateFields: jest.fn((cb) => cb(null, {})) }; const wrapper = shallow(<SignInForm newFunction={newFunction} form={mockForm} />); wrapper.find("#button-id").simulate("click"); expect(newFunction).toHaveBeenCalled(); });
额外注意点
如果你的按钮是Ant Design的Button且设置了htmlType="submit",请确保组件里的表单onSubmit方法正确调用了newFunction,比如:
class SignInForm extends React.Component { handleSubmit = (e) => { e.preventDefault(); this.props.form.validateFields((err, values) => { if (!err) { this.props.newFunction(); // 这里要确保调用传入的函数 } }); }; render() { const { getFieldDecorator } = this.props.form; return ( <Form onSubmit={this.handleSubmit}> {/* 表单项 */} <Button id="button-id" type="primary" htmlType="submit">登录</Button> </Form> ); } }
这种情况下,模拟表单的submit事件会比模拟按钮点击更贴合实际业务逻辑。
内容的提问来源于stack exchange,提问作者Daltron
相关产品推荐
相关产品推荐

