问题描述
我正在为React组件编写测试。它是一个计时器,当您按下一个按钮时开始倒计时,然后在按下相同的按钮时停止计时。我有一个测试用例,试图按一下暂停按钮,等待一秒钟,然后再次按一下暂停按钮,检查计时器以确保已过去一秒钟:
Timer.test.js
render(<Timer />)
const pauseButton = screen.getByText('pause')
const timerOutput = screen.getAllByRole('heading')[1]
describe('Timer',() => {
test('Timer starts counting down when unpaused',done => {
function fetchTime(callback) {
fireEvent.click(pauseButton)
setTimeout(
fireEvent.click(pauseButton),1250
)
return callback(timerOutput)
}
function callback(data) {
try {
expect(data).toHaveTextContent('24:59')
done()
} catch(error) {
done(error)
}
}
fetchTime(callback)
})
})
问题是,测试似乎没有按我希望的方式点击pauseButton
。 Jest在终端上告诉我,当我运行测试时,发现timerOutput
是'25:00'
而不是'24:59'
,看来组件未通过测试。但这是测试的问题,而不是组件的问题。当我在浏览器中运行该应用程序并自己按下按钮时,它将按应有的方式工作。如何使此测试正常运行,并按我希望的方式按下按钮?
解决方法
很难获得关于组件本身的很少信息的准确答案。
首先,我建议在需要处理异步调用时使用async
内的test()
箭头功能,这样您就不必依赖回调地狱了。
除此之外,我将尝试使用jest.useFakeTimers()
,以便您可以提前setTimeout计时器以进行正确测试。看来您的第二个fireEvent.click
从未被解雇,因为测试是同步检查它的。
我只是注意到您最初是请求timerOutput
的,但是在点击事件之后却没有请求。
我建议类似的东西
test('Timer starts counting down when unpaused',async () => {
jest.useFakeTimers();
fireEvent.click(pauseButton)
setTimeout(
() => {fireEvent.click(pauseButton)},1250
)
jest.runPendingTimers(); // This would run the above function
expect(screen.getAllByRole('heading')[1]).toHaveTextContent('24:59')
}
})
实际上,从用户角度断言来看,期望语句会更好,例如:
expect(screen.getByText("24:59")).toBeVisible();
由于您不必担心包含该文本内容的HTML元素