I'm trying to write a jasmine test that has a spy which .and.returnValues
a list of promises. The first several promises are rejections, the last is a success. While the test passes just fine, Node complains with the following:
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): undefined
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): undefined
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 4): undefined
PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 2)
PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 3)
PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 4)
My code is very straight forward: I create a spy, inject it into my code, call my code which will loop calling my spy until it doesn't reject, and then monitor that it was called 5 times. The spy is like this:
var spy = jasmine.createSpy("spy").and.returnValues(
Promise.reject(),
Promise.reject(),
Promise.reject(),
Promise.reject(),
Promise.resolve(true)
);
// Inject the spy...
// This will resolve only when the Promise-returning function it calls resolves without rejecting.
myFunc()
.then(() => {
expect(spy).toHaveBeenCalledTimes(5);
done();
})
.catch();
The code under test has last in it's chain an empty .catch()
to validate that I'm not causing the problem there. AFICT, the problem is that Node sees me doing Promise.reject()
and thinks that is unhandled, when, in fact, it is handled.
How can I properly test rejected promises? I feel like I need something like this for Jasmine.
This is because you catch the rejected promise somewhere later in the event queue and not in the same call stack where the promise is created.
A solution for this is:
var unsafeReject = p => {
p.catch(ignore=>ignore);
return p;
};
var p = Promise.reject("will cause warning");
//will catch reject on queue, not on stack
setTimeout(
()=>p.catch(e=>console.log("reject:",e))
);
var q = unsafeReject(Promise.reject("will NOT cause warning"));
setTimeout(
()=>q.catch(e=>console.log("reject:",e))
);