sinon间谍测试onClick使用样式组件反应组件

时间:2018-02-08 09:57:23

标签: javascript reactjs jestjs styled-components

我正在使用sinon测试反应组件以确认某个功能已被触发onClick

我正在使用styled-components,因此很难找到要点击的元素。

我看到以下错误:

  

方法“模拟”仅用于在单个节点上运行。 0找到了。

我的反应代码如下:

import React, { Component } from 'react'
import styled from 'styled-components'
import PropTypes from 'prop-types'

class Button extends Component {

  pressNumber = () => {
    this.props.updateNumber(this.props.number)
  }

  render() {

    return (
      <ButtonContainer 
        onClick={ this.pressNumber }
      >
        <Number>{ this.props.number }</Number>
      </ButtonContainer>
    )
  }

}

const ButtonContainer = styled.div`
  height: 60px;
  width: 60px;
`

const Number = styled.div`
  color: #fff;
  font-size: 26px;
  font-weight: 300;
`

我的测试看起来像这样:

import { expect } from 'chai'
import { shallow, mount } from 'enzyme'
import sinon from 'sinon'
import React from 'react'
import Button from './index'

describe('Button', () => {

  let wrapper
  const pressNumber = () => {}

  beforeEach(() => {
    wrapper = mount(
      <Button 
        number={1} 
        pressNumber={ pressNumber } 
      />
    )
  })

  it('should call the update pin prop when click is simulated', () => {
    const updatePinClick = sinon.spy();
    wrapper.find('ButtonContainer').simulate('click')
    expect(updatePinClick.calledOnce).to.be.true
  })

})

任何人都可以看到我在这里做错了,如果我使用样式组件有不同的方法。

我看到以下错误

  

方法“模拟”仅用于在单个节点上运行。 0找到了。

2 个答案:

答案 0 :(得分:1)

(披露:我是酶保持者)

你的间谍是updatePinClick,但是你没有把它传递到任何地方,因此无法使用它。此外,Button没有pressNumber道具。

首先,我建议以下一般提示:

  1. 避免.simulate - 如果您想要调用道具,请直接执行,例如.prop('onClick')()
  2. 不要在beforeEach中定义包装器 - 在测试中,重复自己,特别是你正在使用的jsx要好得多。
  3. 避免将字符串传递给.find;它不那么容易导出你想要找到的组件,而是通过引用找到它。
  4. 避免使用noop匹配器 - 即不会在函数中结束的事情,例如.to.be.true。这是因为你可以很容易地输入拼写错误并且它会无声地失败 - expect(object).to.be.yogurt;会愉快地通过,即使这不是一个有效的匹配器。
  5. 首选shallow进行所有测试。仅在必要时使用mount才能使用参考,或测试componentDidMount或其他仅限浏览器的代码。
  6. 具体来说,试试这个:

    import { expect } from 'chai'
    import { shallow, mount } from 'enzyme'
    import sinon from 'sinon'
    import React from 'react'
    import Button from './index'
    
    describe('Button', () => {
      it('should call the update pin prop when click is simulated', () => {
        const updatePinClick = sinon.spy();
        const wrapper = shallow(
          <Button 
            number={1} 
            updateNumber={updatePinClick} 
          />
        );
        wrapper.find('ButtonContainer').prop('onClick')();
        expect(updatePinClick).to.have.property('callCount', 1);
        expect(updatePinClick.calledWith(1)).to.equal(true);
      });
    })
    

答案 1 :(得分:0)

应该可能会遵循LJHarb的建议,但只是为了解决错误:

  

方法“模拟”仅用于在单个节点上运行。 0发现   代替。

使用mount呈现您的<Button/>将呈现所有孩子(及其子女等)。因此,<ButtonContainer/><Number/>已呈现为<div>。因此,搜索ButtonContainer会产生0个结果。