【问题标题】:sinon spy testing onClick react component with styled-componentssinon spy 使用 styled-components 测试 onClick 反应组件
【发布时间】:2018-07-18 20:21:10
【问题描述】:

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

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

我看到以下错误:

方法“simulate”仅用于在单个节点上运行。找到了 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
  })

})

谁能看到我在这里做错了什么,以及我使用样式组件时是否有不同的方法。

我看到以下错误

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

【问题讨论】:

    标签: javascript reactjs jestjs styled-components


    【解决方案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 进行所有测试。仅在需要使用 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);
      });
    })
    

    【讨论】:

    • 我很好奇你作为Enzyme's own docs推荐.simulate的第一点
    • 他们肯定会记录下来;如果您能指出建议的位置,我将很乐意纠正错误。
    【解决方案2】:

    应该可能会遵循 LJHarb 的建议,但要简单地解决错误:

    方法“simulate”仅用于在单个节点上运行。 0 找到 而是。

    使用mount 渲染您的&lt;Button/&gt; 将渲染它它的所有孩子(和他们的孩子,等等)。结果,&lt;ButtonContainer/&gt;&lt;Number/&gt; 已被渲染为&lt;div&gt;s。因此,搜索ButtonContainer 会产生 0 个找到的结果。

    【讨论】:

    • mount 生成的树包含主机节点(DOM 节点)和 React 组件,因此它确实应该定位到 ButtonContainer
    • 抱歉,我的错误。你能帮忙解释一下为什么找不到ButtonContainer吗?
    • 可能是因为它是通过使用 displayName 的字符串找到的 - 并且 styled-components 无法知道模板标签已分配给名为“ButtonContainer”的变量。尝试使用 .debug() 查看树中的真实内容。
    猜你喜欢
    • 1970-01-01
    • 2017-11-01
    • 2019-05-11
    • 1970-01-01
    • 2021-12-25
    • 2021-11-19
    • 2020-01-24
    • 2019-05-02
    • 2018-06-21
    相关资源
    最近更新 更多