Test if a promise is resolved or rejected with Jasmine in Nodejs
Solution 1
To test asynchronous code with jasmine you should use its async syntax, e.g.:
describe('test promise with jasmine', function(done) {
var promise = getRejectedPromise();
promise.then(function() {
// Promise is resolved
done(new Error('Promise should not be resolved'));
}, function(reason) {
// Promise is rejected
// You could check rejection reason if you want to
done(); // Success
});
});
Solution 2
you can now use expectAsync()
Expecting success:
it('expect result', async () => {
...
await expectAsync(someAsyncFunction(goodInput)).toBeResolved(expectedResponse)
})
Expecting failure:
it('expect result', async () => {
...
await expectAsync(someAsyncFunction(badInput)).toBeRejectedWith(expectedResponse)
})
Solution 3
jasmine 2.7 onwards supports returning promises, and would have its fulfilled state tested.
To test for rejection:
it('test promise with jasmine', async () => {
try {
await getRejectedPromise();
} catch (err) {
return;
}
throw new Error('Promise should not be resolved');
});
or yet:
it('test promise with jasmine', async () => {
await getRejectedPromise()
.then(
() => Promise.reject(new Error('Promise should not be resolved')),
() => {});
});
To verify the actual message, besides the usual instanceof/toBe()
, place inside the catch
:
expect(() => { throw err }).toThrow(new MyCustomError('Custom error message'));
The benefit from this approach is to have a nicer fail message on the test output.
Expected function to throw MyCustomError: Custom error message, but it threw Another error message.
Somewhat better than the usual output.
To test for resolved (can't be simpler):
it('test promise with jasmine', async () => {
await getRejectedPromise();
});
Solution 4
You can use finally
block to test promise state:
it('should resolve if auth succeed', (done)=>{
var p = server.login('user', 'password');
p.finally(()=>{
expect(p.isFulfilled()).toBeTruthy();
done();
});
});
You can use isFulfilled
to check if promise was fulfilled and value
method to check the fulfillment value. Corresponding methods for rejection are isRejected
and reason
.
chepukha
Updated on April 24, 2020Comments
-
chepukha about 4 years
I know how to do it in Mocha but want to know how to do it with Jasmine. I tried this
describe('test promise with jasmine', function() { it('expects a rejected promise', function() { var promise = getRejectedPromise(); // return expect(promise).toBe('rejected'); return expect(promise.inspect().state).toBe('rejected'); }); });
However, the state is always
pending
and, of course, the test fails. I couldn't find any example online that I could make it work.Can someone please help me with this?
Thanks.
-
Cmag about 9 yearsGreat! What if you wanted to check the contents of the error being rejected? For some reason I keep getting either
Error: Actual is not a function
orExpected { _subscribers : [ ], _state : 0, _detail : { } } to throw error of type Function.
Thanks! -
Cmag about 9 yearsgreat! yep, thats what im doing... but if i do
expect(reason).toEqual('someerrorstring');
i get the errors i mentioned... -
Leonid Beschastny about 9 years@Cmag I would recommend to inspect rejection reason manually at first, to make sure that it's really what you're expecting it to be. Just use
console.log
or something like that. -
Cmag about 9 yearsconsole.log shows it as [Error blahblah: blah], but if i match it with toEqual(''), it borks..
-
Leonid Beschastny about 9 years@Cmag It's because you're matching Error object with a string.
-
Cmag about 9 yearsyep, got that ... how should i match the error object :)
-
Leonid Beschastny about 9 years@Cmag I would suggest checking that it's an instance of
Error
class and that it containsmsg
property with expected error message. -
sl3dg3 over 8 yearsInstead of
done(new Error('Promise should not be resolved'));
, I'd rather writethrow new Error('Promise should not be resolved');
-
Leonid Beschastny over 8 years@sl3dg3 in this case we should also
return
resulting promise and ensure that jasmine can handle promise rejections correctly. Jasmine had no build-in promise support when I used it for the last time. I switched to mocha a couple of years ago and never used jasmine since, so I'm not aware of the current situation there. If jasmine support promises now, then your proposal is indeed the better alternative to my answer. -
jjalonso almost 8 yearsBut if the promise is already rejected, the the ''callbacks" success and failures never are gonna be called no? On my code is not working because im returning a rejected promise return $q.reject('reason')
-
Leonid Beschastny almost 8 years@jjalonso you are wrong, A+ promise standard demands that appropriate
.then(onresolve, onreject)
callback should be called even if the promise is already resolved/rejected. -
Rui Marques over 7 yearsWith this method, how to you check if the promise was rejected, and check the rejection message?
-
SET001 over 7 years@RuiMarques you can use
isRejected
andreason
methods. I updated my answer. -
nogridbag about 7 yearsI'm maintaining an older library using jasmine 2.0.3 and
done(new Error('Promise should not be resolved'));
does not cause the test case to fail. I've replaced it withexpect('Promise should not be resolved').toBeUndefined();
followed bydone()
but it doesn't seem elegant. -
André Werlang over 6 years
finally()
,isFulfilled()
aren't standard (as of 2017). Please edit your answer to specify external requirements. -
André Werlang over 6 yearsAgreed. I've withdrawn my upvote because the ugly catch clause. Someone else downvoted probably because this note was missing and thought it wouldn't work.
-
André Werlang over 6 yearsStarting from jasmine 2.7, I suggest to use the async/await style (see my answer below.
-
Alexander Mills over 6 yearsThe catch clause is necessary for it to work correctly, it's the normal API for Promises, I don't think it's ugly...would you code something incorrectly just to make it more beautiful? Lol idk
-
André Werlang over 6 yearsThe test() is for an error thrown a couple lines above, it's ugly and lazy coding. See my answer.
-
Alexander Mills over 6 years@AndréWerlang eh, sometimes you have test for error messages, sometimes it's necessary to use catch blocks, perhaps not in this case, but I think mine is more generic, if you need to add more promises to the chain later down the road.
-
Alexander Mills over 6 yearstry/catch is the ugliest coding construct in almost every programming language, imo
-
André Werlang over 6 years@AlexanderMills I know you're kidding, but I' switched from plain promises/then to async/await long ago. Ofc I use the "old way" when it makes sense.
-
Alexander Mills over 6 yearsIf you add a promise above
getRejectedPromise()
this code will swallow errors, because there is no check for what type of error occurs in the error handler. -
Alexander Mills over 6 yearsTherefore this code is not really for general use, it's "pretty" shorthand.
-
malmike21 over 5 yearsAs of jasmine ^2.3, I can not pass parameters into the done function. It would be better to use
done.fail(new Error('error message'))
. Reference to documentation -
malmike21 over 5 yearsIf you are using jasmine 3 and above, you can pass an error parameter in the done function. Reference to documentation
-
isnot2bad over 4 yearsAdditional note: It is crucial to always use
await
(await expectAsync(...)
) - otherwise the test will always succeed, no matter if the promise is rejected or not, and no matter if the test expects it to be rejected or resolved! -
isnot2bad over 4 yearsThis answer is wrong in several ways: (1)
isFulfilled()
is not an official method ofPromise
according to the ECMAScript standard. (2) Even if it were, it would always returntrue
insidefinally
, asfulfilled
means the promise is either rejected or resolved, which is always true whenfinally
is called. -
Jack Fuchs over 4 yearsActually not true. It can also just be returned from within the spec.
return expectAsync(pi).toBeResolvedTo(3.14);
-
Coderer over 3 yearsThis is the most idiomatic answer and should be accepted. (The current accepted answer was good when it was given, but your solution is objectively better now.)
-
Coderer over 3 yearsThis used to be a good answer but at this point I'd expect everybody to be on a new enough version to use
expectAsync
, which allows you to write tests that "look like Jasmine".