2

我有一个 Input 组件,它接受一个 prop 方法并在用户输入内容时调用它。代码本身按预期工作,但由于某些原因,测试失败。它认为没有调用 prop 方法。为什么会这样?出于测试目的,我使用 Jest 和 react-testing-library。

第二个问题。在实际应用中,我的想法是测试传递给该 prop 方法的参数。它是否被认为是一个实现测试(我知道我应该测试它)?

输入.js

export default function Input({ onChange }) {
  return <input onChange={onChange} />;
}

测试

import React from "react";
import { render, act, cleanup, fireEvent } from "react-testing-library";
import Input from "./input";

describe("Input tests", () => {
  afterEach(cleanup);

  it("Should call prop function", () => {
    const onChange = jest.fn();
    const { getByTestId } = render(<Input onChange={onChange} />);
    const input = getByTestId("input");

    act(() => {
      fireEvent.change(input, { target: { value: "Q" } });
    });

    expect(onChange).toHaveBeenCalled();
  });
});

https://codesandbox.io/s/y229669nvx

4

2 回答 2

1

读完这篇文章后,看起来不针对事件处理程序断言是设计使然。尽管它似乎在 React 16.5 中工作,但是,使用 16.8.x 失败。如果您想测试这些功能,我建议您转向酶。

测试react-testing-library失败(但是,您会注意到,在运行测试时,输入的值实际上会改变):https ://codesandbox.io/s/n3rvy891n4

测试enzyme成功:https ://codesandbox.io/s/lx34ny41nl

于 2019-03-02T23:46:23.520 回答
0

您的测试不起作用的原因是您正在使用它getByTestId来查找您的元素。getByTestId查找具有data-testid属性的 DOM 节点。

为了使您的测试通过,您有多种选择。

你可以在data-testid你的input:中添加一个<input data-testid="input" onChange={onChange} />。这会起作用,但是,最好尽可能避免使用测试 ID。

在实际应用程序中,您的输入将使用 a 呈现label,我们可以利用它:

const { getByLabelText } = render(
  <label>
    My input
    <Input onChange={onChange} />
  </label>
)
const input = getByLabelText('My input')

另一种解决方案是使用containerwhich 是render. 它是一个 DOM 节点——就像 RTL 中的所有其他东西一样——所以你可以使用常用的 DOM API:

const { container } = render(<Input onChange={onChange} />)
// Any of these would work
const input = container.firstChild
const input = container.querySelector('input')

作为旁注,我同意与酶相比,RTL 测试似乎更复杂。这是有充分理由的。RTL 推动您测试您的应用程序,就好像它是一个黑盒一样。一开始这有点难,但最终会导致更好的测试。

另一方面,Enzyme 默认模拟大多数事情,并允许您与组件实现进行交互。根据我的经验,这在开始时看起来更容易,但会产生脆弱的测试。

如果您需要入门帮助,我鼓励您加入频谱频道。

于 2019-03-04T09:13:55.443 回答