如何测试由反应测试库中的 onChange 处理程序更新的道具?

Kim*_*Kim 4 unit-testing reactjs react-testing-library

我在输入上有一个 onChange 处理程序,我正在尝试根据我在 Dom 测试库文档中阅读的内容(此处此处)来测试该处理程序。

我的代码中的一个区别是,我使用 props,而不是使用本地状态来控制输入值。所以 onChange 函数实际上是调用另一个函数(也通过 props 接收),它更新已“提升”到另一个组件的状态。最终,输入值作为 prop 被组件接收,并更新输入值。

我正在模拟 props 并尝试做一些简单的测试来证明 onChange 处理程序按预期工作。

我希望在更改处理程序中调用的函数被调用的次数与测试中使用 fireEvent.change 的次数相同,这适用于:

const { input } = setup();
fireEvent.change(input, { target: { value: "" } });
expect(handleInstantSearchInputChange).toHaveBeenCalledTimes(1);
Run Code Online (Sandbox Code Playgroud)

我希望 input.value 是从原始模拟道具设置中读取的,这适用于:

  const { input } = setup();
  expect(input.value).toBe("bacon");
Run Code Online (Sandbox Code Playgroud)

但是,我正在做一些愚蠢的事情(看起来根本不理解模拟函数),并且我无法弄清楚为什么以下块不更新 input.value,并继续从读取 input.value 设置原始的模拟道具设置。

由于期望“”/收到“培根”<=在原始道具中设置,因此失败

fireEvent.change(input, { target: { value: "" } });
expect(input.value).toBe("");
Run Code Online (Sandbox Code Playgroud)

问题:如何编写测试来证明 input.value 已根据下面的代码更改?我假设我需要模拟handleInstantSearchInputChange函数来执行某些操作,但我还不知道我在这里做什么。

感谢您提供有关如何执行和/或更好地理解这一点的任何建议。

测试文件

import React from "react";
import InstantSearchForm from "../../components/InstantSearchForm";
import { render, cleanup, fireEvent } from "react-testing-library";

afterEach(cleanup);

let handleInstantSearchInputChange, props;
  handleInstantSearchInputChange = jest.fn();
  props = {
    foodSearch: "bacon",
    handleInstantSearchInputChange: handleInstantSearchInputChange
  };

const setup = () => {
  const utils = render(<InstantSearchForm {...props} />);
  const input = utils.getByLabelText("food-search-input");
  return {
    input,
    ...utils
  };
};

it("should render InstantSearchForm correctly with provided foodSearch prop", () => {
  const { input } = setup();
  expect(input.value).toBe("bacon");
});

it("should handle change", () => {
  const { input } = setup();
  fireEvent.change(input, { target: { value: "" } });
  expect(input.value).toBe("");
  fireEvent.change(input, { target: { value: "snickerdoodle" } });
  expect(input.value).toBe("snickerdoodle");
});
Run Code Online (Sandbox Code Playgroud)

成分

import React from "react";
import PropTypes from "prop-types";

const InstantSearchForm = props => {
  const handleChange = e => {
    props.handleInstantSearchInputChange(e.target.value);
  };
  return (
    <div className="form-group">
      <label className="col-form-label col-form-label-lg" htmlFor="food-search">
        What did you eat, fatty?
      </label>
      <input
        aria-label="food-search-input"
        className="form-control form-control-lg"
        onChange={handleChange}
        placeholder="e.g. i ate bacon and eggs for breakfast with a glass of whole milk."
        type="text"
        value={props.foodSearch}
      />
    </div>
  );
};

InstantSearchForm.propTypes = {
  foodSearch: PropTypes.string.isRequired,
  handleInstantSearchInputChange: PropTypes.func.isRequired
};

export default InstantSearchForm;
Run Code Online (Sandbox Code Playgroud)

bit*_*ien 6

您思考测试的方式有点不正确。该组件的行为如下:

  1. 当将文本作为 prop 传递时,foodSearch它会正确呈现。
  2. 组件在发生变化时调用适当的处理程序。

所以只测试以上内容。

触发更改事件后 prop会发生什么foodSearch不是该组件(InstantSearchForm)的责任。该责任在于处理该状态的方法。因此,您需要专门作为单独的测试来测试该处理程序方法。