React Testing:React Shallow Rendering单元测试中的事件处理程序

时间:2015-09-04 22:47:48

标签: javascript unit-testing testing reactjs mocha

背景

React Shallow Rendering tests

我正在尝试学习如何使用React Shallow Rendering TestUtil并让测试通过,直到我向两者添加了onClick事件处理程序;似乎我在Accordion.toggle Accordion.test.jsthis.toggle Accordian.js中使用的Accordian.test.js函数必定存在一些差异......但我无法弄明白

问题

如何才能让npm install中的两个突出显示的测试通过?

重现步骤

  1. 克隆https://github.com/trevordmiller/shallow-rendering-testing-playground
  2. npm run dev
  3. npm run test:watch - 当您点击“Lorem Ipsum”
  4. 时,看到该组件正常工作
  5. Option Explicit Dim clsobject As clsComboBox Private Sub CommandButton1_Click() Dim ctlcombobox As ComboBox Set ctlcombobox = Me.Controls.Add("Forms.ComboBox.1", "ComboBox1", True) Set clsobject = New clsComboBox Set clsobject.cmboControl = ctlcombobox With ctlcombobox .Top = 100 .Left = 5 .Width = 200 .Height = 25 .Visible = True .List = Array("1", "2") End With End Sub - 看到测试失败

4 个答案:

答案 0 :(得分:9)

有许多问题阻止您的测试通过。

查看测试"默认情况下应该处于非活动状态":

    测试中的
  1. Accordion.toggleAccordion类的属性,代码中的this.toggleAccordion类实例的属性 - 所以在这种情况下你要比较两件不同的东西。要访问'实例'在测试中,您可以将Accordion.toggle替换为Accordion.prototype.toggle。如果它不是你的构造函数中的this.toggle = this.toggle.bind(this);,那将会有效。这引出了我们的第二点。

  2. 在函数上调用.bind()时,它会在运行时创建一个新函数 - 因此您无法将其与原始Accordion.prototype.toggle进行比较。解决这个问题的唯一方法就是拉开"绑定"函数取决于渲染的结果:

    let toggle = result.props.children[0].props.onClick;
    
    assert.deepEqual(result.props.children, [
      <a onClick={toggle}>This is a summary</a>,
      <p style={{display: 'none'}}>This is some details</p>
    ]);
    
  3. 至于你的第二次失败测试&#34;点击后应该变为活动状态&#34;:

    1. 您尝试调用不存在的result.props.onClick()。您打算致电result.props.children[0].props.onClick();

    2. React中存在一个错误,需要全局&#34;文档&#34;在使用浅渲染调用setState时要声明的变量 - 如何在每种情况下解决这个问题超出了这个问题的范围,但是快速解决问题的方法是在调用之前添加global.document = {}; onClick方法。换句话说,你的原始测试有:

      result.props.onClick();
      

      现在应该说:

      global.document = {};
      result.props.children[0].props.onClick();
      

      参见&#34;修复破碎的setState()&#34; on this pagethis react issue

答案 1 :(得分:3)

Marcin Grzywaczewski写了一篇很棒的article,其中包含一个测试点击处理程序的解决方法,该处理程序适用于浅层渲染。

给定一个带有onClick prop的嵌套元素和一个绑定到组件的上下文的处理程序:

render() {
  return (
    <div>
      <a className="link" href="#" onClick={this.handleClick}>
        {this.state.linkText}
      </a>
      <div>extra child to make props.children an array</div>
    </div>
  );
}

handleClick(e) {
  e.preventDefault();
  this.setState({ linkText: 'clicked' });
}

您可以在事件对象中手动调用onClick prop的函数值:

it('updates link text on click', () => {
  let tree, link, linkText;

  const renderer = TestUtils.createRenderer();
  renderer.render(<MyComponent />);

  tree = renderer.getRenderOutput();
  link = tree.props.children[0];
  linkText = link.props.children;

  // initial state set in constructor
  expect(linkText).to.equal('Click Me');

  // manually invoke onClick handler via props
  link.props.onClick({ preventDefault: () => {} });

  tree = renderer.getRenderOutput();
  link = tree.props.children[0];
  linkText = link.props.children;

  expect(linkText).to.equal('Clicked');
});

答案 2 :(得分:1)

要测试onClick等用户事件,您必须使用TestUtils.Simulate.clickSadly

  

现在不可能将ReactTestUtils.Simulate与Shallow渲染一起使用,我认为要遵循的问题应该是:https://github.com/facebook/react/issues/1445

答案 3 :(得分:0)

我已经成功测试了我的无状态组件中的点击。方法如下:

我的组件:

import './ButtonIcon.scss';

import React from 'react';
import classnames from 'classnames';

const ButtonIcon = props => {
  const {icon, onClick, color, text, showText} = props,
    buttonIconContainerClass = classnames('button-icon-container', {
      active: showText
    });

  return (
    <div
      className={buttonIconContainerClass}
      onClick={onClick}
      style={{borderColor: color}}>
      <div className={`icon-container ${icon}`}></div>
      <div
        className="text-container"
        style={{display: showText ? '' : 'none'}}>{text}</div>
    </div>
  );
}

ButtonIcon.propTypes = {
  icon: React.PropTypes.string.isRequired,
  onClick: React.PropTypes.func.isRequired,
  color: React.PropTypes.string,
  text: React.PropTypes.string,
  showText: React.PropTypes.bool
}

export default ButtonIcon;

我的测试:

it('should call onClick prop when clicked', () => {
  const iconMock = 'test',
    clickSpy = jasmine.createSpy(),
    wrapper = ReactTestUtils.renderIntoDocument(<div><ButtonIcon icon={iconMock} onClick={clickSpy} /></div>);

  const component = findDOMNode(wrapper).children[0];

  ReactTestUtils.Simulate.click(component);

  expect(clickSpy).toHaveBeenCalled();
  expect(component).toBeDefined();
});

重要的是包装组件:

<div><ButtonIcon icon={iconMock} onClick={clickSpy} /></div>

希望有所帮助!