React输入onChange模拟在使用Jest和Enzyme时未更新值

4

我有一个如下的函数式组件:

const Input = () => {
  const [value, updateValue] = useState("");
  return (
    <input
      type="text"
      id="input"
      value={value}
      onChange={(e) => {
        updateValue(e.target.value);
      }}
    />
  );
};

export default Input;

并且测试如下

const event = { target: { value: "Q" } };
input.simulate("change", event);
expect(input.prop("value")).toBe("Q");

问题在于事件的模拟没有更新状态。 我也尝试过使用wrapper.update(),但它不起作用。
你可以在这里运行测试。

除了@skyboyer的答案外,您还应该查看https://testing-library.com/docs/react-testing-library/intro,它可以非常简化组件测试。 - Gabriele Petrioli
2个回答

8

组件更新后,您的input变量仍指向旧的包装器。

包装器(除根包装器外)是不可变的,因此您需要再次使用.find()查找元素。

所以,如果您

const event = { target: { value: "Q" } };
input.simulate("change", event);
expect(wrapper.find("input").prop("value")).toBe("Q");

你会通过的。

PS在使用Enzyme进行测试时,最好总是避免使用中间变量。


1
它可以工作。但是当我使用findById并且有多个输入时,我在沙盒中会收到此类错误。https://codesandbox.io/s/input-unit-test-enzyme-2lp7i @skyboyer - NIsham Mahsin
你实例化了两个输入框,它们的id分别为"1""2",但是你却使用选择器"#heart"来查找它们。 - skyboyer
抱歉,即使用心了。我已经改变了态度。 - NIsham Mahsin
所以你的第三方组件呈现为<Input .... id="heart"> <input .... id="heart" /> </Input>。您可以通过console.log(input.debug())自行查看。你能做什么?您可以更具体(.find("input#heart"))或仅取第一个元素(.find("#heart").at(0))。或者您可以使用shallow()而不是mount()。或者您可以切换到react-testing-library(它使用不同的方法)。 - skyboyer

1

对于那些像@NishamMahsin的案例一样有多个输入的人。 我遇到了同样的问题,并从模拟“更改”后包装器未更新。#1999找到了可行的解决方案。

简而言之:

.simulate('change', {target: {name: 'inputFirstName', value: 'value'}})

我在这方面花了很长时间,希望对这里的某些人有所帮助...


这取决于将更新状态的函数处理程序。在您的答案中,就像objState[event.target.name] = event.target.value一样。因此,您应该存根事件对象以匹配状态设置器的适当使用。 - KeitelDOG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接