我有一个具有简单输入和按钮的React Hook,如果没有输入,该按钮将被禁用,并且启用该按钮后将执行提取操作:
function MyComponent() {
const [ value, setValue ] = useState('')
function apiRequest() {
if (!value) {
return
}
axios.get('url')
.then(console.log)
.catch(console.log)
}
return (
<div>
<input onChange={e => setValue(e.target.value)} value={value} />
<button disabled={!value} onClick={apiRequest}>
Submit
</button>
</div>
)
}
我用Enzyme编写了两个测试。第一个测试被禁用的道具是否正确,第二个测试它是否实际获取。
it('sets the disabled prop appropriately', function() {
const wrapper = mount(<MyComponent />)
const input = wrapper.find('input')
const btn = wrapper.find('button')
expect(btn.prop('disabled')).toBeTruthy()
input.simulate('change', 'abc123')
expect(btn.prop('disabled')).toBeFalsy()
})
it('fetches on submit', function () {
const wrapper = mount(<MyComponent />)
const input = wrapper.find('input')
const btn = wrapper.find('button')
input.simulate('change', 'abc123')
btn.simulate('click')
expect(axios.get).toHaveBeenCalled()
})
但是不幸的是,要使第二项测试生效,需要启用该按钮,因此必须首先输入文本。因此,实际上,第二项测试也无意中也测试了禁用的道具,因为如果禁用的道具设置不正确,它将失败(onClick
不会触发)。
我遵循了React的recommended approach
test React components without relying on their implementation details
这是react-testing-library的核心原则,所以我纯粹是在测试副作用。我使用的是酶而不是酶,因为我的团队目前正在使用酶
我如何能够重写第二个测试,以便只能 测试提取?预先感谢。
编辑:或者,有几种方法可以重写它以正确测试提取?
答案 0 :(得分:1)
您可以做的一件事是将<div>
替换为<form>
,然后向其中添加onSubmit={e => apiRequest(value)}
,以便按钮可以保持禁用状态,并且您仍可以继续进行测试而无需介绍不必要的外部因素。
此外,将function apiRequest() {...}
移出组件。它可以使用value
作为参数,而不是依赖周围的范围。
// You could even export this separately and make a test exclusively for this
// without also having to test the form itself
function apiRequest ( value ) {
if (!value) {
return
}
axios.get('url')
.then(console.log)
.catch(console.log)
}
function MyComponent() {
const [ value, setValue ] = useState('')
return (
<form onSubmit={e => { e.preventDefault(); apiRequest(value); }}>
<input onChange={e => setValue(e.target.value)} value={value} />
<button disabled={!value}>
Submit
</button>
</form>
)
}
答案 1 :(得分:0)
我相信您肯定是在测试行为,而不是实现细节。
如果您说的是setState()
,那将依赖于实现细节(请确保它不适用于功能组件,这就是为什么它是错误的模式)。
使用RTL,您仍然必须在单击按钮之前更改输入,这里没有区别。
唯一的事情是实现细节,它依赖于axios
本身。您可以使用nock
处理任何库发出的任何请求。但是我不确定这是否值得。