【问题标题】:How can I test if a function is called onChange in a functional React component?如何测试函数是否在功能性 React 组件中调用 onChange?
【发布时间】:2023-03-27 22:57:01
【问题描述】:

我有一个需要测试的简单功能组件。

const Product = () => {
    const handleOnChange = (value) => {
        console.log(value);
    }

    return (
        <div>
            <input type="text" onChange={(e) => {handleOnChange(e.target.value)}} />
        </div>
    )
}

我想测试当输入改变它的值时是否调用了“handleOnChange”函数。我试过了:

let wrapper;
beforeEach(() => {
    wrapper = shallow(<Product />);
});
describe('Product interactions', () => {
it('should call handleOnChange function on input change', () => {

  const mockedhandleOnChange = jest.fn(); 
  wrapper.handleOnChange = mockedhandleOnChange;
  wrapper.find('input').simulate('change', {target: {value: 10}});
  expect(mockedhandleOnChange).toHaveBeenCalledTimes(1);    
});

});

当然它不起作用,因为我无法通过“wrapper.handleOnChange”访问该函数。

请帮忙!

【问题讨论】:

  • handleOnChange 是函数内部声明的常量,外部不可用。顺便说一句,通常最好测试函数内部的内容是否已被调用或 UI 本身是否已更改。在这个例子中你应该断言 console.log 它被调用(我知道它不是真正的代码)
  • Emanuele,非常感谢您的评论。你完全正确。

标签: reactjs testing jestjs enzyme


【解决方案1】:
it('should call handleOnChange function on input change', () => {
    const wrapper = shallow(<Product />);
    const input = wrapper.find('input');
    input.simulate('change', { target: { value: 10 } });
    input = wrapper.find('input');
    expect(input.props().value).toEqual(10);
  });

【讨论】:

    【解决方案2】:

    您应该使 React state 成为单一事实来源。目前,您的程序中的input 保持着自己的状态。更好的选择是将其用作Controlled Components。一旦您使用input 作为受控组件,您的程序将如下所示:

    class Product extends React.Component {
      constructor(props) {
        super(props);
        this.state = {value: ''};
      }
      handleOnChange = (value) => {
        this.setState({ value })
      }
    
      return (
        <div>
          <input id="input1" type="text" value={this.state.value} onChange={(e) => {handleOnChange(e.target.value)}} />
        </div>
      )
    }
    

    一旦你有了上面的代码,对input进行验证和测试就会简单得多。您需要调用inputonChange,之后您可以验证状态。您的测试将如下所示:

    let wrapper;
    beforeEach(() => {
      wrapper = shallow(<Product />);
    });
    describe('Product interactions', () => {
      it('should call handleOnChange function on input change', () => {
        wrapper.find('#input1').getNode().props.onChange({
          target: { value: '123' }
        });
        expect(wrapper.state().value).toEqual('123');
      });
    });
    

    【讨论】:

    • 穆克什,非常感谢您的帖子。它帮助我与课程联系起来。但是,我现在尝试通过使用带有钩子的功能组件来避免它们。这使测试变得更加困难。
    猜你喜欢
    • 1970-01-01
    • 2021-09-04
    • 2020-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    相关资源
    最近更新 更多