如何使用Enzyme结合快照测试reduxForm包装的展示组件?
解决Enzyme测试被ReduxForm和WithStyles包装的Login组件问题
我来帮你搞定这个测试问题~ 你的核心困扰是现在默认导出的Login组件被reduxForm和withStyles两层高阶组件包装了,所以直接shallow渲染要么找不到store,要么只能拿到外层的Connect组件快照,没法获取到实际的展示组件内容。
下面给你两种可行的解决方案:
方案1:导出未包装的原始Login组件(推荐)
最简单的方式是在组件文件里额外导出未被任何高阶组件包装的原始展示组件,这样测试时直接用这个原始组件就行,不用处理redux和样式的包装逻辑:
修改你的组件代码:
// 导出原始的展示组件,供测试使用 export const Login = ({userName, onSubmit, classes}) => { // 你的组件逻辑和JSX return ( <Form id="form" onSubmit={onSubmit}> <Card className={classes.card}> <CardHeader ... /> {/* 其他组件内容 */} </Card> </Form> ); }; // 保持原有的默认导出,供业务代码使用 export default reduxForm({form: "login"})(withStyles(loginStyles)(Login));
然后在测试文件里导入这个原始组件,直接测试:
import { Login } from './your-login-component-path'; // 注意这里导入的是命名导出的原始组件 it("renders correctly_NEW", () => { // 模拟需要的props,包括classes(可以用jest.mock或者直接传空对象/模拟样式) const mockClasses = { card: 'mock-card-class' }; const wrapper = shallow(<Login userName="test" onSubmit={() => {}} classes={mockClasses} {...state(false)} />); expect(wrapper).toMatchSnapshot(); });
这样快照里就会是你想要的Login组件本身的JSX内容啦。
方案2:不解开组件导出,逐层dive穿透高阶组件
如果你不想修改组件的导出结构,可以通过多次dive()来穿透外层的高阶组件,但需要注意层级顺序:
你的默认导出组件层级是:Connect(Form(WithStyles(Login))),所以需要一步步dive进去:
it("renders correctly_NEW", () => { const wrapper = shallow( <Provider store={configureStore()}> <Login {...state(false)} /> </Provider> ); // 第一步dive:从Provider到Connect组件 // 第二步dive:从Connect到Form组件 // 第三步dive:从Form到WithStyles组件 // 第四步dive:从WithStyles到最终的Login展示组件 const loginWrapper = wrapper.dive().dive().dive().dive(); expect(loginWrapper).toMatchSnapshot(); });
不过这种方式的缺点是如果后续高阶组件的层级变化了,测试代码也得跟着改,不如方案1稳定。
另外提醒一下,测试样式组件时,如果你不需要验证样式细节,传模拟的classes props或者用jest mock掉withStyles也是常见的做法哦。
内容的提问来源于stack exchange,提问作者Roberto
相关产品推荐
相关产品推荐

