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

sinon spy testing onClick react component with styled-components

我正在使用 sinon 来测试一个 React 组件以确认触发了一个函数 onClick

我正在使用 styled-components,因此发现很难定位要单击的元素。

我看到以下错误:

Method “simulate” is only meant to be run on a single node. 0 found instead.

我的反应代码如下所示:

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
  })

})

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

我看到以下错误

Method “simulate” is only meant to be run on a single node. 0 found instead.

(披露:我是酶维护者)

您的间谍是 updatePinClick,但您没有将其传递到任何地方,因此无法使用。此外,Button 不接受 pressNumber 属性。

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

  1. 避免 .simulate - 如果你想调用一个道具,直接做,比如 .prop('onClick')().
  2. 不要在 beforeEach 中定义包装器 - 在测试中,最好自己重复一遍,特别是你正在使用的 jsx。
  3. 避免将字符串传递给 .find;导出要查找的组件并通过引用查找它更容易。
  4. 避免 noop 匹配器 - 即,不以函数结尾的东西,例如 .to.be.true。这是因为您很容易打错字,它会默默地失败 - expect(object).to.be.yogurt; 会很高兴地通过,即使那不是有效的匹配器。
  5. 首选 shallow 进行所有测试。仅在需要使用 refs 或测试 componentDidMount 或其他仅限浏览器的代码时才使用 mount

具体来说,试试这个:

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);
  });
})

应该 可能会听从 LJHarb 的建议,但是为了简单地解决错误:

Method “simulate” is only meant to be run on a single node. 0 found instead.

使用 mount 渲染您的 <Button/> 将渲染它 全部 children(以及它们的 children,并且很快)。结果,<ButtonContainer/><Number/> 被渲染成 <div>。因此搜索 ButtonContainer 会找到 0 个结果。