如何使用Jest在事件侦听器中测试异步功能?

时间:2020-05-29 14:19:16

标签: javascript async-await jestjs event-listener

我有一个运行异步函数的事件侦听器,并在完成后从DOM中删除了一些元素:

async function fetchAndRemove() {
  try {
    const response = await fetch('/endpoint-that-returns-json')

    const result = await response.json()
    if (result.status === 'Success') {
      document.querySelector('.my-element').remove()
    }
  } catch (error) {
    console.log(error)
  }
}

function setupListeners () {
  const button = document.querySelector('.my-button')
  button.addEventListener('click', () => {
    fetchAndRemove()
  })
}


setupListeners()

在我的测试中,我有:

import fetch from 'jest-fetch-mock';

test('it removes the element after clicking', () => {
  fetch.mockResponse(JSON.stringify({ status: 'Success' }))
  setupListeners()
  document.querySelector('.my-button').click() // .click comes from JSDOM

  expect(document.querySelector('.my-element')).toBeNull()
}

但是这不起作用,因为我相信测试会成功进行,设置事件侦听器并单击按钮会同步运行,并且不会等待异步工作完成。

我尝试了这个主意,但没有好结果:

test('it removes the element after clicking', async () => {
  fetch.mockResponse(JSON.stringify({ status: 'Success' }))
  setupListeners()
  await Promise.resolve(document.querySelector('.my-button').click())

  expect(document.querySelector('.my-element')).toBeNull()
}

1 个答案:

答案 0 :(得分:1)

这是错误的,因为DOM事件不涉及承诺,并且await Promise.resolve是多余的:

await Promise.resolve(document.querySelector('.my-button').click())

它会产生一按延迟,仅此而已。

由于fetchAndRemove是在其定义的同一模块中引用的,因此无法进行侦查,因此fetch Promise应该被链接起来以保持正确的执行顺序。

考虑到fetch是间谍,它可以是:

  fetch.mockResponse(JSON.stringify({ status: 'Success' }))
  setupListeners()
  document.querySelector('.my-button').click()
  await fetch.mock.results[0].value; // delay for fetch()
  await null; // another delay for res.json()
  expect(fetch).toBeCalledWith('/endpoint-that-returns-json')
  expect(document.querySelector('.my-element')).toBeNull()