从外部组件反应测试库触发回调

use*_*545 3 reactjs jestjs react-testing-library react-hooks

我试图弄清楚如何使用 jest 和 React 测试库来测试作为 props 给出的回调,以对功能组件做出反应。

示例场景:我正在测试一个呈现模式的组件。当用户单击模式上的“关闭”按钮时,父组件将隐藏模式。所以逻辑是这样的:

 const ParentComp = () => {
  const [openModal, setOpenModal] = useState(false);
  return (
   <>
     <MyModal showModal={openModal} onClose={() => setOpenModal(false)} />
     <button data-testid="open-modal-button" onClick={()=> setOpenModal(true)}>Test</button>
  </>
 }

const MyModal = ({showModal, onClose}) => {
  return (
   {showModal && <>
     <div>This is a modal</div>
     <button data-testid="close-modal-button" onClick={onClose}>Close</button>
  </>
  }
 }
Run Code Online (Sandbox Code Playgroud)

我在父组件的测试中模拟模态,因为我不想依赖实际的模态组件。使用 React 测试库,如何触发父组件中的 onClose 以便测试 setOpenModal(false)?

jest.mock('../MyModal');
beforeEach(() => {
  MyModal.mockImplementation(() => <div data-testid="my-modal" />);
});

it('should close the modal' () => {
const { container, getByTestId } = render(
    <MyParentComp />
);
const openModalButton = getByTestId('open-modal-button');

fireEvent.click(openModalButton);
const myModal = getByTestId('my-modal');

expect(myModal).toBeDefined();

//How to test setOpenModal(false) on parent component?
Run Code Online (Sandbox Code Playgroud)

});

sli*_*wp2 5

对于您的示例,实际上不需要模拟MyModal组件,除非MyModal组件具有许多外部依赖项。请参阅testing-recipes.html#mocking-modules

\n

为了触发该onClose功能,您仍然需要onClickMyModal

\n

此外,您没有正确模拟 MyModal 组件。这是一个工作示例:

\n

ParentComp.tsx:

\n
import React, { useState } from \'react\';\nimport { MyModal } from \'./MyModal\';\n\nexport const ParentComp = () => {\n  const [openModal, setOpenModal] = useState(false);\n  return (\n    <>\n      <MyModal showModal={openModal} onClose={() => setOpenModal(false)} />\n      <button data-testid="open-modal-button" onClick={() => setOpenModal(true)}>\n        Test\n      </button>\n    </>\n  );\n};\n
Run Code Online (Sandbox Code Playgroud)\n

MyModal.tsx:

\n
import React from \'react\';\n\nexport const MyModal = ({ showModal, onClose }) => {\n  return (\n    showModal && (\n      <>\n        <div>This is a modal</div>\n        <button data-testid="close-modal-button" onClick={onClose}>\n          Close\n        </button>\n      </>\n    )\n  );\n};\n
Run Code Online (Sandbox Code Playgroud)\n

ParentComp.test.tsx:

\n
import { fireEvent, render } from \'@testing-library/react\';\nimport React from \'react\';\nimport { ParentComp } from \'./ParentComp\';\n\nfunction MockedMyModal({ onClose, showModal }) {\n  return (\n    showModal && (\n      <>\n        <div>This is a mocked modal</div>\n        <button data-testid="my-modal" onClick={onClose}>\n          Close\n        </button>\n      </>\n    )\n  );\n}\n\njest.mock(\'./MyModal\', () => {\n  return { MyModal: MockedMyModal };\n});\n\ndescribe(\'65038548\', () => {\n  afterAll(() => {\n    jest.resetAllMocks();\n  });\n  it(\'should open the modal\', () => {\n    const { getByTestId } = render(<ParentComp></ParentComp>);\n    const openModalButton = getByTestId(\'open-modal-button\');\n\n    fireEvent.click(openModalButton);\n    const myModal = getByTestId(\'my-modal\');\n\n    expect(myModal).toBeDefined();\n  });\n\n  it(\'should close the modal\', () => {\n    const { getByTestId, queryByText } = render(<ParentComp></ParentComp>);\n    const openModalButton = getByTestId(\'open-modal-button\');\n    fireEvent.click(openModalButton);\n\n    const closeModalButton = getByTestId(\'my-modal\');\n    expect(closeModalButton).toBeDefined();\n\n    fireEvent.click(closeModalButton);\n\n    expect(queryByText(\'This is a mocked modal\')).toBeNull();\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

为什么使用queryByText而不是getByTestId,请参阅断言元素不存在

\n

单元测试结果:

\n
 PASS  examples/65038548/ParentComp.test.tsx\n  65038548\n    \xe2\x9c\x93 should pass (34 ms)\n\n----------------|---------|----------|---------|---------|-------------------\nFile            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n----------------|---------|----------|---------|---------|-------------------\nAll files       |    87.5 |      100 |   66.67 |   85.71 |                   \n ParentComp.tsx |    87.5 |      100 |   66.67 |   85.71 | 8                 \n----------------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       1 passed, 1 total\nSnapshots:   0 total\nTime:        5.848 s\n
Run Code Online (Sandbox Code Playgroud)\n

源代码:https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/65038548

\n