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
属性。
首先,我建议以下一般提示:
- 避免
.simulate
- 如果你想调用一个道具,直接做,比如 .prop('onClick')()
.
- 不要在
beforeEach
中定义包装器 - 在测试中,最好自己重复一遍,特别是你正在使用的 jsx。
- 避免将字符串传递给
.find
;导出要查找的组件并通过引用查找它更容易。
- 避免 noop 匹配器 - 即,不以函数结尾的东西,例如
.to.be.true
。这是因为您很容易打错字,它会默默地失败 - expect(object).to.be.yogurt;
会很高兴地通过,即使那不是有效的匹配器。
- 首选
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 个结果。
我正在使用 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
属性。
首先,我建议以下一般提示:
- 避免
.simulate
- 如果你想调用一个道具,直接做,比如.prop('onClick')()
. - 不要在
beforeEach
中定义包装器 - 在测试中,最好自己重复一遍,特别是你正在使用的 jsx。 - 避免将字符串传递给
.find
;导出要查找的组件并通过引用查找它更容易。 - 避免 noop 匹配器 - 即,不以函数结尾的东西,例如
.to.be.true
。这是因为您很容易打错字,它会默默地失败 -expect(object).to.be.yogurt;
会很高兴地通过,即使那不是有效的匹配器。 - 首选
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 个结果。