使用反应测试库和触发功能模拟出一个子组件

时间:2020-07-14 14:03:34

标签: reactjs unit-testing react-testing-library

因此,我想在容器组件上测试方法“ handleUpdate”。在该容器组件中有一个表单组件。

./ MyContainer.jsx

const MyContainer = ({ handleUpdate }) => (
  <MyForm onSubmit={handleUpdate} />
);

./ MyForm.jsx

const MyForm = ({ onSubmit }) => {
  const [error, setError] = useState();
  const [nameValue, setNameValue] = useState();

  handleChange(event) {
    setNameValue(event.target.value);
  }
  
  handleSubmit(event) {
    event.preventDefault();
    if (!nameValue) { setError("Name is required"); }
    onSubmit(nameValue);
  }

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="nameInput">Name: </label>
      <input type="text" name="name" onChange={handleChange} id="nameInput" />
      {error && <p>{error}</p>}
      <button name="save button" type="submit">Submit</button>
    </form>
  );
};

此表单组件已针对用户可以与之进行的交互进行了单独测试:

./ MyForm.test.js

const mockSubmit = jest.fn();
function setup() {
  render(<MyForm onSubmit={mockSubmit} />);
}

it('has a required field', () => {
  setup();

  userEvent.click(screen.getByRole('button', { name: 'save button' }));

  expect(screen.getByText('Name is required.'));
});

it('saves', () => {
  setup();

  // make sure name has a value
  userEvent.type(screen.getByLabelText(/^name$/i), 'John');

  userEvent.click(screen.getByRole('button', { name: 'save button' }));
  expect(mockSubmit).toHaveBeenCalled();
});

现在,我想测试表单组件何时触发提交,容器组件中是否触发了“ handleUpdate”。但我不想设置输入值等来保存表单:

./ MyContainer.test.js

const mockUpdate = jest.fn();
function setup() {
  render(<MyContainer handleUpdate={mockUpdate} />);
}

it('handles an update', () => {
  setup();

  // problem is here
  //
  // the input name is already tested in ./MyForm.test.js
  // so I don't want to have to do this again...
  userEvent.type(screen.getByLabelText(/^name$/i'), 'John');

  userEvent.click(screen.getByRole('button', { name: 'save button' }));

  expect(mockUpdate).toHaveBeenCalled();
});

因此,理想情况下,我想模拟MyForm组件并在测试中手动触发onSubmit。

您将如何处理?

尝试以下操作:

我在考虑使用jest.mock('./MyForm.test.js')的路线:

jest.mock('./MyForm.js', () => () => {
  return <p>test</p>;
});

const mockUpdate = jest.fn();
function setup() {
  render(<MyContainer handleUpdate={mockUpdate} />);
}

it('handles an update', () => {
  setup();

  screen.debug(); // <- this shows that MyForm is now replaced with "<p>test</p>"
  // how to trigger the handleUpdate from this?

  userEvent.click(screen.getByRole('button', { name: 'save button' }));

  expect(mockUpdate).toHaveBeenCalled();
});

但是我该如何触发“ handleUpdate”呢?

0 个答案:

没有答案