admin管理员组文章数量:1410674
I am testing a function that returns a 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
I am testing a function that returns a 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
Share
asked Sep 11, 2018 at 19:49
dayulolidayuloli
17.1k18 gold badges75 silver badges132 bronze badges
9
- 1 Define "never". – robertklep Commented Sep 11, 2018 at 19:52
-
As in the example given above -
new Promise((resolve, reject) => {})
would never settle right? – dayuloli Commented Sep 11, 2018 at 19:57 -
You can't really. The only way to ensure that the promise won't ever be resolved is proofing that there are no
resolve
/reject
functions alive that still reference it. So something likegc.collect(); const a = gc.memory(); promise = null; gc.collect(); const b = gc.memory(); return a - b < 0
could possibly do it, but it doesn't look reliable. – Bergi Commented Sep 11, 2018 at 19:57 - @dayuloli did you wait an infinite amount of time to make sure? – robertklep Commented Sep 11, 2018 at 19:57
- 1 @dayuloli See stackoverflow./a/30654451/1048572 (I think I got the syntax wrong, and I also doubt that it works at all, but you can try) – Bergi Commented Sep 11, 2018 at 20:18
4 Answers
Reset to default 3robertklep's answer works, but you'd have to wait for 5 seconds before the test pletes. For unit tests, 5 seconds is simply too long.
As you've suggested, you can integrate the lolex
library into robertklep's solution, to avoid the wait.
(I am also using a Symbol
instead of the string 'timeout'
, in case your promise resolves, by coincidence, also resolves with the string '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');
});
});
});
});
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:
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') }
)
]);
});
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):
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);
});
本文标签: javascriptMochaHow to test for unsettled promiseStack Overflow
版权声明:本文标题:javascript - Mocha - How to test for unsettled promise? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744948509a2633933.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论