简体   繁体   English

React,如何模拟用户输入进行单元测试?

[英]React, how to simulate user input for unit testing?

I have been trying to unit test a react component that takes in user input.我一直在尝试对接收用户输入的 React 组件进行单元测试。 More specifically I'm trying to test the onChange function within the react component.更具体地说,我正在尝试测试 react 组件中的onChange函数。 However I can't seem to set the input value, I've tried a few different ways suggested on the internet and none seem to work.但是我似乎无法设置输入值,我尝试了互联网上建议的几种不同方法,但似乎都不起作用。 Below is the component I'm trying to test.下面是我要测试的组件。

class Input extends Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    /* Check if max length has been set. If max length has been
    set make sure the user input is less than max Length, otherwise
    return before updating the text string. */
    if(this.props.maxLength) {
      if(event.target.value.length > this.props.maxLength) {
        return;
      }
    }
    this.setState({ value: event.target.value });
  }

  render () {
    const { disabled, label, maxLength, multiline, type, value, ...others} = this.props;
    const theme = themeable(others.theme);

    let inputClassName = classNames({
      "input": type !== 'checkbox',
      "checkbox": type == 'checkbox',
      disabled,
      multiline,
      value,
      [`${this.props.className}`]: !!this.props.className
    });

    return (
      <div {...theme(1, 'container')}>
        {this.props.label ? <label htmlFor={this.props.htmlFor} {...theme(2, 'label')}>{label}</label> : null}
          <input value={this.state.value} {...theme(3, ...inputClassName)} onChange={this.handleChange} type={type} />
      </div>
    );
  }
}

I found this issue: https://github.com/airbnb/enzyme/issues/76 and tried the suggestions towards the bottom, I keep getting either undefined or a blank string.我发现了这个问题: https : //github.com/airbnb/enzyme/issues/76并尝试了底部的建议,我不断收到未定义或空白字符串。 I tried levibuzolic's suggestion of using enzyme's simulate change, which can be seen below.我尝试了 levibuzolic 的使用酶模拟变化的建议,可以在下面看到。 However this just returns AssertionError: expected '' to equal 'abcdefghij'然而,这只是返回AssertionError: expected '' to equal 'abcdefghij'

it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    result.find('input').simulate('change', {target: {value: 'abcdefghijk'}});
    expect(result.state().value).to.equal("abcdefghij");
});

Then I tried takkyuuplayer's suggestion which is also below.然后我尝试了 takkyuuplayer 的建议,这也在下面。 This also fails with AssertionError: expected '' to equal 'abcdefghij'这也失败了AssertionError: expected '' to equal 'abcdefghij'

  it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    result.find('input').node.value = 'abcdefghijk';
    expect(result.state().value).to.equal("abcdefghij");
  });

I found this article: https://medium.com/javascript-inside/testing-in-react-getting-off-the-ground-5f569f3088a#.f4gcjbaak and tried their way which also failed.我找到了这篇文章: https : //medium.com/javascript-inside/testing-in-react-getting-off-the-ground-5f569f3088a#.f4gcjbaak并尝试了他们的方法,但也失败了。

  it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    let input = result.find('input');
    input.get(0).value = 'abcdefghijk';
    input.simulate('change');
    expect(result.state().value).to.equal("abcdefghij");
  });

Finally I tried using the react test utils as suggested by Simulating text entry with reactJs TestUtils , below is the code I tried, however this failed with the error message: TypeError: Cannot read property '__reactInternalInstance$z78dboxwwtrznrmuut6wjc3di' of undefined最后,我尝试按照使用reactJs TestUtils 模拟文本输入的建议使用 react 测试工具,下面是我尝试的代码,但是失败并显示错误消息: TypeError: Cannot read property '__reactInternalInstance$z78dboxwwtrznrmuut6wjc3di' of undefined

  it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    let input = result.find('input');
    TestUtils.Simulate.change(input, { target: { value: 'abcdefghijk' } });
    expect(result.state().value).to.equal("abcdefghij");
  });

So how does one simulate user input so they can test the onChange function?那么如何模拟用户输入以便他们可以测试onChange函数呢?

You seem to have a bug in your Input component.您的 Input 组件中似乎存在错误。 When event.target.value.length > this.props.maxLength you never set the actual state, leaving the state.value as '' .event.target.value.length > this.props.maxLength您永远不会设置实际状态, state.valuestate.value'' It seems you expected it to have been set to the value, but truncated to maxLength.似乎您希望它已设置为该值,但被截断为 maxLength。 You'll need to add that yourself:您需要自己添加:

handleChange(event) {
  /* Check if max length has been set. If max length has been
  set make sure the user input is less than max Length, otherwise
  return before updating the text string. */
  if (this.props.maxLength) {
    if (event.target.value.length > this.props.maxLength) {
      // ** Truncate value to maxLength
      this.setState({ value: event.target.value.substr(0, this.props.maxLength) });
      return;
    }
  }
  this.setState({ value: event.target.value });
}

... then, the following test works and passes: ...然后,以下测试有效并通过:

it('Make sure inputted text is shorter than max length', () => {
  const result = mount(<Input maxLength={10}></Input>);
  result.find('input').simulate('change', { target: { value: '1234567890!!!' } });
  expect(result.state().value).to.equal("1234567890");
});

I have been trying to unit test a react component that takes in user input.我一直在尝试对接收用户输入的 React 组件进行单元测试。 More specifically I'm trying to test the onChange function within the react component.更具体地说,我正在尝试测试 react 组件中的onChange函数。 However I can't seem to set the input value, I've tried a few different ways suggested on the internet and none seem to work.但是我似乎无法设置输入值,我尝试了互联网上建议的几种不同方法,但似乎都不起作用。 Below is the component I'm trying to test.下面是我要测试的组件。

class Input extends Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    /* Check if max length has been set. If max length has been
    set make sure the user input is less than max Length, otherwise
    return before updating the text string. */
    if(this.props.maxLength) {
      if(event.target.value.length > this.props.maxLength) {
        return;
      }
    }
    this.setState({ value: event.target.value });
  }

  render () {
    const { disabled, label, maxLength, multiline, type, value, ...others} = this.props;
    const theme = themeable(others.theme);

    let inputClassName = classNames({
      "input": type !== 'checkbox',
      "checkbox": type == 'checkbox',
      disabled,
      multiline,
      value,
      [`${this.props.className}`]: !!this.props.className
    });

    return (
      <div {...theme(1, 'container')}>
        {this.props.label ? <label htmlFor={this.props.htmlFor} {...theme(2, 'label')}>{label}</label> : null}
          <input value={this.state.value} {...theme(3, ...inputClassName)} onChange={this.handleChange} type={type} />
      </div>
    );
  }
}

I found this issue: https://github.com/airbnb/enzyme/issues/76 and tried the suggestions towards the bottom, I keep getting either undefined or a blank string.我发现了这个问题: https : //github.com/airbnb/enzyme/issues/76并尝试了底部的建议,我不断收到未定义或空白字符串。 I tried levibuzolic's suggestion of using enzyme's simulate change, which can be seen below.我尝试了 levibuzolic 的使用酶模拟变化的建议,可以在下面看到。 However this just returns AssertionError: expected '' to equal 'abcdefghij'然而,这只是返回AssertionError: expected '' to equal 'abcdefghij'

it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    result.find('input').simulate('change', {target: {value: 'abcdefghijk'}});
    expect(result.state().value).to.equal("abcdefghij");
});

Then I tried takkyuuplayer's suggestion which is also below.然后我尝试了 takkyuuplayer 的建议,这也在下面。 This also fails with AssertionError: expected '' to equal 'abcdefghij'这也失败了AssertionError: expected '' to equal 'abcdefghij'

  it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    result.find('input').node.value = 'abcdefghijk';
    expect(result.state().value).to.equal("abcdefghij");
  });

I found this article: https://medium.com/javascript-inside/testing-in-react-getting-off-the-ground-5f569f3088a#.f4gcjbaak and tried their way which also failed.我找到了这篇文章: https : //medium.com/javascript-inside/testing-in-react-getting-off-the-ground-5f569f3088a#.f4gcjbaak并尝试了他们的方法,但也失败了。

  it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    let input = result.find('input');
    input.get(0).value = 'abcdefghijk';
    input.simulate('change');
    expect(result.state().value).to.equal("abcdefghij");
  });

Finally I tried using the react test utils as suggested by Simulating text entry with reactJs TestUtils , below is the code I tried, however this failed with the error message: TypeError: Cannot read property '__reactInternalInstance$z78dboxwwtrznrmuut6wjc3di' of undefined最后,我按照使用 reactJs TestUtils 模拟文本输入的建议尝试使用 react 测试工具,下面是我尝试过的代码,但是失败并显示错误消息: TypeError: Cannot read property '__reactInternalInstance$z78dboxwwtrznrmuut6wjc3di' of undefined

  it('Make sure inputted text is shorter than max length', function() {
    const result = mount(<Input maxLength={10}></Input>);
    let input = result.find('input');
    TestUtils.Simulate.change(input, { target: { value: 'abcdefghijk' } });
    expect(result.state().value).to.equal("abcdefghij");
  });

So how does one simulate user input so they can test the onChange function?那么如何模拟用户输入以便他们可以测试onChange函数呢?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM