异步功能的表现与我对Jest的预期不同

时间:2017-11-14 00:20:58

标签: javascript asynchronous jestjs

Javascript Jest测试框架documentation表示我需要在回调函数中添加done()来测试异步函数,否则函数将在测试完成后返回,因此测试将失败。我已将Jest添加到我的package.json,以及以下两个文件:

src.js:

function fetchData(cb) {
  setTimeout(cb, 2000, 'peanut butter')
}

module.exports = fetchData

src.test.js:

const fetchData = require('./src')

test('the data is peanut butter', () => {
  function callback(data) {
    expect(data).toBe('peanut butter')
    // no done() method!
  }

  fetchData(callback);
})

我通过上面的代码传递测试,但我认为我应该得到一个失败的测试,因为我的测试文件中没有done()。我的fetchData()方法不是异步的吗?

编辑:根据Nicholas的回答,我将代码更改为:

src.js:

function fetchData(cb) {
  setTimeout(cb, 2000, 'peanut')
}

module.exports = fetchData

src.test.js:

const fetchData = require('./src')

test('the data is peanut butter', () => {
  function callback(data) {
    expect(data).toBe('peanut butter')
    done()
  }

  fetchData(callback);
})

测试运行者应根据Jest文档评估期望/断言并且失败(花生通过,花生酱预期),但仍显示通过测试。< / p>

此外,Jest文档说:

If done() is never called, the test will fail, which is what you want to happen

测试在回调中使用和不使用done()方法传递,并且有和没有正确的(peanut butter)参数传递给回调(即所有四个变量都通过)。

2 个答案:

答案 0 :(得分:2)

如果未将done作为参数传递,则测试运行器会将代码视为同步,并且不会等待发生特殊情况 - 在这种情况下调用done

因此,在你的断言/期望有机会运行之前,测试被标记为成功的

答案 1 :(得分:1)

您的fetchData本身是异步的,Jest对此没有影响。另一方面,Jest需要知道测试何时结束,这通常是测试函数退出时,但只包括同步代码。在你的情况下,当你的测试函数退出时,你没有调用任何断言,Jest认为这是成功的(因为没有失败)。

为了证明没有调用断言,我将使用expect.assertions(number)仅在调用number断言时才通过测试。例如,如果在示例中将其设置为1:

test('the data is peanut butter', () => {
  // Require exactly 1 assertion to pass the test
  expect.assertions(1)

  function callback(data) {
    expect(data).toBe('peanut butter')
  }

  fetchData(callback)
})

您将看到错误消息:

● the data is peanut butter

  expect.assertions(1)

  Expected one assertion to be called but received zero assertion calls.

如您所见,没有任何断言被调用。除了演示目的之外,您可以使用expect.assertions来确保在未调用断言时测试失败。

对于任何异步任务,您需要让Jest知道测试是异步的,您需要在完成时通知Jest。一种方法是使用done回调。当您的测试函数采用一个参数(通常称为done)时,Jest会将其视为异步测试,并等待您调用done()回调,或达到超时阈值(默认值:5s) 。在您编辑的示例中,您的函数采用零参数,而您对done()的调用不是Jest的回调。

test('done callback', done => {
  //                  ^^^^ 1 argument
  // Jest waits until this callback is called or the timeout was reached.
  // ...
})

test('no callback argument', () => {
  //                         ^^ no argument
  // Test finishes as soon as the function exits
  // ...
})

这很少被使用,因为承诺现在更常见,它们使这更简单,因为你可以返回承诺,Jest将等待它完成而无需任何额外的设置。此外,您可以使用asyncawait使其更加出色,因为它是承诺之上的语法糖。

另请参阅Testing Asynchronous Code - PromisesTesting Asynchronous Code - Async/Await