我试图监视useState React钩子,但我总是测试失败
这是我的React组件:
const Counter= () => {
const[counter, setCounter] = useState(0);
const handleClick=() => {
setCounter(counter + 1);
}
return (
<div>
<h2>{counter}</h2>
<button onClick={handleClick} id="button">increment</button>
</div>
)
}
counter.test.js:
it('increment counter correctlry', () => {
let wrapper = shallow(<Counter/>);
const setState = jest.fn();
const useStateSpy = jest.spyOn(React, 'useState');
useStateSpy.mockImplementation((init) => [init, setState]);
const button = wrapper.find("button")
button.simulate('click');
expect(setState).toHaveBeenCalledWith(1);
})
不幸的是,这不起作用,我得到了测试失败的消息:
expected 1
Number of calls: 0
6条答案
按热度按时间tpxzln5u1#
diedu的回答给我指引了正确的方向,我想出了这个解决方案:
1.从react中模拟使用状态,以返回jest.fn()作为useState:
1.1也要在后面立即导入useState--现在它将是ejestmock(从jest.fn()调用返回)
1.稍后,在beforeEach中,将其设置为原始useState,以便在所有情况下不需要它被模仿
1.在测试中,根据需要模拟它:
临别赠言:虽然从概念上讲,在单元测试这个“黑盒”中弄脏双手可能有点错误,但有时候这样做确实非常有用。
axr492tv2#
您需要使用
React.useState
而不是单个导入useState
。我认为是关于代码如何被转译的,正如您在babel repl中看到的,来自单个导入的
useState
最终与模块导入的useState
不同。因此,您监视
_react.default.useState
,但您的组件使用_react.useState
。由于需要函数属于一个对象,因此在单个导入中进行监视似乎是不可能的,这里有一个非常广泛的指南,解释了mocking/spying模块https://github.com/HugoDF/mock-spy-module-import的方法正如@Alex Mackay所提到的,你可能想改变你对测试react组件的想法,建议你转向react-testing-library,但如果你真的需要坚持使用酶,你不需要走那么远来模拟react library本身。
x8goxv8g3#
你只需要在你的测试文件中导入React,就像:
然后你可以使用mock函数。
wn9m85ua4#
令人烦恼的是,Codesandbox目前在测试模块上遇到了麻烦,所以我不能发布一个工作示例,但我会试图解释为什么mocking
useState
通常是一件坏事。用户并不关心是否调用了
useState
,他们关心的是 * 当我单击increment时,计数应该增加1 *,因此这就是您应该测试的内容。如果你对这种测试风格感兴趣,一定要看看
@testing-library
。我大约2年前从enzyme
切换过来,从那以后就没有碰过它。whlutmcx5#
你应该使用React.useState()而不是useState(),但还有其他方法...在React中,您可以使用此配置设置useState而不使用React
简体中文
jk9hmnmh6#
你不需要使用`Import * as React from 'react',因为如果你在代码中不使用React.useState,它会导致问题。
我只需要做以下几件事就可以了: