0

我正在为 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',并且似乎组件未能通过测试。但这是测试的问题,而不是组件的问题;当我在浏览器中运行应用程序并自己按下按钮时,它会按应有的方式工作。如何让这个测试正常工作,并按我想要的方式点击按钮?

4

1 回答 1

0

几乎没有关于组件本身的信息,很难得到准确的答案。

首先,当您需要处理异步调用时,我建议您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 语句会更好,例如:

expect(screen.getByText("24:59")).toBeVisible();

因为您不关心包含该文本内容的 HTML 元素

于 2020-10-07T00:19:24.020 回答