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
)参数传递给回调(即所有四个变量都通过)。
答案 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将等待它完成而无需任何额外的设置。此外,您可以使用async
和await
使其更加出色,因为它是承诺之上的语法糖。
另请参阅Testing Asynchronous Code - Promises和Testing Asynchronous Code - Async/Await