[英]Mocha - How to test for unsettled promise?
I am testing a function that returns a promise. 我正在测试一个返回promise的函数。 I want to assert that, in certain conditions, the returned promise would never settle (doesn't resolve nor reject).
我想断言,在某些情况下,返回的承诺永远不会解决(不解决也不拒绝)。
How can I test this with Mocha? 我如何用摩卡测试?
If I run the following: 如果我运行以下内容:
describe('under certain conditions', function () {
let promise;
beforeEach(function () {
promise = new Promise((resolve, reject) => {});
});
it('should hang forever', function () {
return promise;
});
});
I get the following error: 我收到以下错误:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves
Let's start by stating that practically speaking, it's not possible to validate that the promise never settles: at some point you have to decide that it has taken too long for the promise to settle, and assume that it will never settle after that point. 让我们首先说明,实际上,不可能证实承诺永远不会解决:在某些时候你必须决定承诺结算已经花了太长时间,并假设它在此之后永远不会解决。
Here's a solution that would place that point at 5 seconds: 这是一个将该点置于5秒的解决方案:
it('should hang forever', function() {
// Disable Mocha timeout for this test.
this.timeout(0);
// Wait for either a timeout, or the promise-under-test to settle. If the
// promise that settles first is not the timeout, fail the test.
return Promise.race([
new Promise(resolve => setTimeout(resolve, 5000, 'timeout')),
promise.then(
() => { throw Error('unexpectedly resolved') },
() => { throw Error('unexpectedly rejected') }
)
]);
});
robertklep 's answer works, but you'd have to wait for 5 seconds before the test completes. robertklep的回答是有效的,但你必须等待5秒才能完成测试。 For unit tests, 5 seconds is simply too long.
对于单元测试,5秒太长了。
As you've suggested, you can integrate the lolex
library into robertklep's solution, to avoid the wait. 正如您所建议的,您可以将
lolex
库集成到robertklep的解决方案中,以避免等待。
(I am also using a Symbol
instead of the string 'timeout'
, in case your promise resolves, by coincidence, also resolves with the string 'timeout'
) (我也使用
Symbol
而不是字符串'timeout'
,以防你的承诺解决,巧合,也解决了字符串'timeout'
)
import { install } from 'lolex';
describe('A promise', function () {
let clock;
before(function () { clock = install() });
after(function () { clock.uninstall() });
describe('under certain conditions', function () {
const resolvedIndicator = Symbol('resolvedIndicator');
const forever = 600000; // Defining 'forever' as 10 minutes
let promise;
beforeEach(function () {
promise = Promise.race([
new Promise(() => {}), // Hanging promise
new Promise(resolve => setTimeout(resolve, forever, resolvedIndicator)),
]);
});
it('should hang forever', function () {
clock.tick(forever);
return promise.then((val) => {
if (val !== resolvedIndicator) {
throw Error('Promise should not have resolved');
}
}, () => {
throw Error('Promise should not have rejected');
});
});
});
});
Try this: 试试这个:
describe('under certain conditions', function () {
let promise;
beforeEach(function () {
promise = new Promise((resolve, reject) => {
// promise.reject();
});
});
it('should hang forever', function (done) {
const onRejectOrResolve = () => {
done(new Error('test was supposed to hang'));
};
promise
.then(onRejectOrResolve)
.catch(onRejectOrResolve);
setTimeout(() => {
done();
}, 1000);
});
});
You can introduce a race between the never resolving promise and a reference promise with a suitable timeout using Promise.race
( MDN ): 您可以使用
Promise.race
( MDN )在永不解决的promise和引用promise之间引入适当的超时:
const p1 = new Promise((resolve, reject) => { }); const p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 5 * 1000, 'promise2'); }); Promise.race([p1, p2]) .then(value => { console.log(value); });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.