如何在进行 React 快照测试时模拟 react-bootstrap 组件?

huangapple go评论120阅读模式
英文:

How to mock react-bootstrap components while doing snapshot testing in React?

问题

我正在开发一个使用react-bootstrap UI构建的React项目。虽然有很多编写测试用例的选项,但我选择了使用Jest进行快照测试。

我有一个组件,它包裹在一个Bootstrap Modal中,生成的快照中始终带有null值。如果删除Modal包装器并直接返回表单,那么它可以正常生成输出。

我想要模拟Bootstrap的Modal,以返回一个简单的实现(同时保持库的其余部分不受影响),并减少传递给react-bootstrap库所需的各种属性的复杂性。

组件代码示例如下:

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, 
exports[`Snapshot testing of MyComponent`] = `null`;
英文:

I am working on a react project which is built using react-bootstrap UI. While there are a lot of options for writing test cases, I opted for Snapshot testing using Jest.


I have a component which is wrapped inside a bootstrap Modal and is always rendered with a null value in the generated snapshot. If remove the Modal wrapper and directly return the form then it generates the output just fine.

I want to mock the bootstrap Modal so as to return a simple implementation (while keeping rest of the library un-touched) and reduce the complexities of passing all the various props required by the react-boostrap library.

Component:
function MyComponent(){
return (
&lt;div&gt;
&lt;Modal
show={props.showReviewModal}
onHide={handleClose}
className=&quot;well-connection-review&quot;
&gt;
&lt;Modal.Header closeButton&gt;
&lt;Modal.Title className=&quot;m-auto p-auto&quot;&gt;
Modal Title
&lt;/Modal.Title&gt;
&lt;/Modal.Header&gt;
&lt;Form
noValidate
validated={validated}
onSubmit={(e) =&gt; handleValidation(e)}
&gt;
&lt;Modal.Body&gt;
&lt;Form.Row className=&quot;m-2 d-flex align-items-center&quot;&gt;
&lt;Form.Group as={Col} controlId=&quot;formPowerCompany&quot; className=&quot;m-1&quot;&gt;
&lt;Form.Label className=&quot;label&quot;&gt;Power Company&lt;/Form.Label&gt;
&lt;Select
isClearable={true}
name=&quot;PowerCompany&quot;
options={ELECTRIC_PROVIDERS}
className=&quot;basic-multi-select well-connection-report-filters&quot;
onChange={PowerCompanyChange}
value={powerCompany}
isSearchable={false}
placeholder=&quot;Power Company&quot;
/&gt;
&lt;/Form.Group&gt;
&lt;/Form.Row&gt;
&lt;Form.Row className=&quot;m-2 d-flex align-items-center&quot;&gt;
&lt;Form.Group as={Col} controlId=&quot;formMeterID&quot; className=&quot;m-1&quot;&gt;
&lt;Form.Label className=&quot;label&quot;&gt;Meter ID&lt;/Form.Label&gt;
&lt;Form.Control
type=&quot;text&quot;
value={meterId}
name=&quot;meterId&quot;
onChange={handleChange}
autoComplete=&quot;off&quot;
/&gt;
&lt;Form.Control.Feedback type=&quot;invalid&quot;&gt;
Please enter an ID
&lt;/Form.Control.Feedback&gt;
&lt;/Form.Group&gt;
&lt;/Form.Row&gt;
&lt;/Modal.Body&gt;
&lt;Modal.Footer className=&quot;mr-3&quot;&gt;
&lt;Button
variant=&quot;primary&quot;
onClick={() =&gt; handleClose()}
type=&quot;submit&quot;
&gt;
Close
&lt;/Button&gt;
&lt;/Modal.Footer&gt;
&lt;/Form&gt;
&lt;/Modal&gt;
&lt;/div&gt;
);
}
export default MyComponent;
Test Case for the component:
import React from &quot;react&quot;; 
import MyComponent from &quot;../MyComponent&quot;; 
import renderer from &quot;react-test-renderer&quot;; 
describe(&quot;Snapshot testing of MyComponent&quot;, () =&gt; { 
it(&quot;MyComponent snapshot&quot;, () =&gt; { 
const MyComponent = renderer.
create(&lt;MyComponent message={&quot;message&quot;} /&gt;).toJSON(); 
expect(MyComponent).toMatchSnapshot(); 
}); 
});
Snapshot output for the component:
// Jest Snapshot v1, 
exports[`Snapshot testing of MyComponent`] = `null`;

答案1

得分: 1

以下是翻译好的部分:

"Posting a solution here so that it helps anyone who stumbles upon it in future. The easiest way to do away with the complexities of passing the required props and mocking the various methods of the react-boostrap library components is to mock the individual components of the library and return a custom implementation for it.

The idea here is to NOT test the structure of components of the external library but to just test the structure of your own components.

Solution:

// MyComponents.test.js
import React from &quot;react&quot;;
import MyComponent from &quot;../MyComponent&quot;;
import renderer from &quot;react-test-renderer&quot;;
// this code will be auto hoisted by Jest
jest.mock(&quot;react-bootstrap&quot;, () =&gt; {
// get the original boostrap library
const orgBootstrap = jest.requireActual(&quot;react-bootstrap&quot);
// mock the Modal component
const mockModal = ({ children }) =&gt; { return &lt;div&gt;{children}&lt;/div&gt;; };
// mock the sub-components of the Modal
mockModal.Header = (props) =&gt; &lt;div&gt;{props.children}&lt;/div&gt;;
mockModal.Body = (props) =&gt; &lt;div&gt;{props.children}&lt;/div&gt;;
mockModal.Footer = (props) =&gt; &lt;div&gt;{props.children}&lt;/div&gt;;
// return your modified boostrap library instance with mocked Modal
const mockBoostrap = { __esModule: true, ...orgBootstrap, Modal: mockModal };
return mockBoostrap;
});
describe(&quot;Snapshot testing of MyComponent&quot;, () =&gt; {
it(&quot;MyComponent snapshot&quot;, () =&gt; {
const MyComponent = renderer.
create(&lt;MyComponent /&gt;).toJSON();
expect(MyComponent).toMatchSnapshot();
});
});
英文:

Posting a solution here so that it helps anyone who stumbles upon it in future. The easiest way to do away with the complexities of passing the required props and mocking the various methods of the react-boostrap library components is to mock the individual components of the library and return a custom implementation for it.

The idea here is to NOT test the structure of components of the external library but to just test the structure of your own components.

Solution:
// MyComponents.test.js
import React from &quot;react&quot;; 
import MyComponent from &quot;../MyComponent&quot;; 
import renderer from &quot;react-test-renderer&quot;; 
// this code will be auto hoisted by Jest
jest.mock(&quot;react-bootstrap&quot;, () =&gt; { 
// get the original boostrap library
const orgBootstrap = jest.requireActual(&quot;react-bootstrap&quot;); 
// mock the Modal component
const mockModal = ({ children }) =&gt; { return &lt;div&gt;{children}&lt;/div&gt;; }; 
// mock the sub-components of the Modal
mockModal.Header = (props) =&gt; &lt;div&gt;{props.children}&lt;/div&gt;; 
mockModal.Body = (props) =&gt; &lt;div&gt;{props.children}&lt;/div&gt;; 
mockModal.Footer = (props) =&gt; &lt;div&gt;{props.children}&lt;/div&gt;; 
// return your modified boostrap library instance with mocked Modal
const mockBoostrap = { __esModule: true, ...orgBootstrap, Modal: mockModal }; 
return mockBoostrap; 
});
describe(&quot;Snapshot testing of MyComponent&quot;, () =&gt; { 
it(&quot;MyComponent snapshot&quot;, () =&gt; { 
const MyComponent = renderer.
create(&lt;MyComponent /&gt;).toJSON(); 
expect(MyComponent).toMatchSnapshot(); 
}); 
});

huangapple
  • 本文由 发表于 2023年2月24日 12:02:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75552512.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定