React快照测试中如何Mock react-bootstrap组件?
问题:React-Bootstrap Modal包裹的组件快照测试返回null
我在开发一个用React-Bootstrap做UI的React项目,用Jest做快照测试。当组件被Bootstrap Modal包裹时,生成的快照始终是null;去掉Modal直接返回表单的话,快照就正常。我想Mock Bootstrap Modal,只返回一个简单实现,不影响库的其他部分,减少传递React-Bootstrap各类Props的复杂度。
组件代码
function MyComponent(){ return ( <div> <Modal show={props.showReviewModal} onHide={handleClose} className="well-connection-review" > <Modal.Header closeButton> <Modal.Title className="m-auto p-auto"> Modal Title </Modal.Title> </Modal.Header> <Form noValidate validated={validated} onSubmit={(e) => handleValidation(e)} > <Modal.Body> <Form.Row className="m-2 d-flex align-items-center"> <Form.Group as={Col} controlId="formPowerCompany" className="m-1"> <Form.Label className="label">Power Company</Form.Label> <Select isClearable={true} name="PowerCompany" options={ELECTRIC_PROVIDERS} className="basic-multi-select well-connection-report-filters" onChange={PowerCompanyChange} value={powerCompany} isSearchable={false} placeholder="Power Company" /> </Form.Group> </Form.Row> <Form.Row className="m-2 d-flex align-items-center"> <Form.Group as={Col} controlId="formMeterID" className="m-1"> <Form.Label className="label">Meter ID</Form.Label> <Form.Control type="text" value={meterId} name="meterId" onChange={handleChange} autoComplete="off" /> <Form.Control.Feedback type="invalid"> Please enter an ID </Form.Control.Feedback> </Form.Group> </Form.Row> </Modal.Body> <Modal.Footer className="mr-3"> <Button variant="primary" onClick={() => handleClose()} type="submit" > Close </Button> </Modal.Footer> </Form> </Modal> </div> ); } export default MyComponent;
测试用例代码
import React from "react"; import MyComponent from "../MyComponent"; import renderer from "react-test-renderer"; describe("Snapshot testing of MyComponent", () => { it("MyComponent snapshot", () => { const MyComponent = renderer. create(<MyComponent message={"message"} />).toJSON(); expect(MyComponent).toMatchSnapshot(); }); });
快照输出结果
// Jest Snapshot v1, [link to jest docs] exports[`Snapshot testing of MyComponent`] = `null`;
解决方案
原因分析
React-Bootstrap的Modal组件在show属性为false时,会直接渲染null。你的测试用例里没有传递showReviewModal props,组件内Modal的show值默认是false,导致整个组件快照为null。
方法1:传递Props让Modal显示
直接给测试组件传入showReviewModal={true},让Modal正常渲染:
import React from "react"; import MyComponent from "../MyComponent"; import renderer from "react-test-renderer"; describe("Snapshot testing of MyComponent", () => { it("MyComponent snapshot", () => { const component = renderer.create( <MyComponent message={"message"} showReviewModal={true} /> ).toJSON(); expect(component).toMatchSnapshot(); }); });
方法2:Mock React-Bootstrap的Modal组件(推荐)
如果不想依赖Modal内部逻辑,可通过Jest Mock掉Modal,让它直接渲染子元素,同时保留React-Bootstrap其他组件的原实现:
步骤1:创建Mock文件
在项目根目录新建__mocks__文件夹,然后创建react-bootstrap.js文件:
// __mocks__/react-bootstrap.js import React from 'react'; import * as ReactBootstrap from 'react-bootstrap'; // 自定义Modal的Mock实现 const MockModal = ({ children, ...props }) => ( <div data-testid="mock-modal" {...props}> {children} </div> ); MockModal.Header = ({ children, ...props }) => ( <div data-testid="mock-modal-header" {...props}> {children} </div> ); MockModal.Title = ({ children, ...props }) => ( <div data-testid="mock-modal-title" {...props}> {children} </div> ); MockModal.Body = ({ children, ...props }) => ( <div data-testid="mock-modal-body" {...props}> {children} </div> ); MockModal.Footer = ({ children, ...props }) => ( <div data-testid="mock-modal-footer" {...props}> {children} </div> ); // 导出时保留其他组件的原实现,仅替换Modal export default { ...ReactBootstrap, Modal: MockModal, };
步骤2:在测试中启用Mock
修改测试用例,让Jest使用自定义的Mock:
import React from "react"; import MyComponent from "../MyComponent"; import renderer from "react-test-renderer"; // 启用react-bootstrap的Mock jest.mock('react-bootstrap'); describe("Snapshot testing of MyComponent", () => { it("MyComponent snapshot", () => { const component = renderer.create( <MyComponent message={"message"} /> ).toJSON(); expect(component).toMatchSnapshot(); }); });
这样Mock后,Modal会渲染为简单的div容器,无论show属性是什么,都会正常渲染子元素,快照就能生成完整内容,同时Form、Button等其他React-Bootstrap组件不受影响。
内容的提问来源于stack exchange,提问作者Salvino D'sa
相关产品推荐
相关产品推荐

