1

我在输入上有一个 onChange 处理程序,我正在尝试根据我在 Dom 测试库文档herehere中阅读的内容进行测试。

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

我在嘲笑道具并尝试做一些简单的测试来证明 onChange 处理程序按预期工作。

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

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

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

  const { input } = setup();
  expect(input.value).toBe("bacon");

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

这失败了,期待“”/收到“培根”<=在原始道具中设置

fireEvent.change(input, { target: { value: "" } });
expect(input.value).toBe("");

问题:如何编写测试来证明 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");
});

零件

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;
4

1 回答 1

4

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

  1. 当将文本作为道具传递时,foodSearch它会正确呈现。
  2. 组件在更改时调用适当的处理程序。

所以只测试上面的。

触发 change 事件后 prop发生foodSearch的事情不是这个组件(InstantSearchForm)的责任。该责任在于处理该状态的方法。因此,您可能希望将该处理程序方法专门作为单独的测试进行测试。

于 2019-02-24T07:08:29.633 回答