jest: async/await .not.toThrow idiomatic check
To check that async functions are not throwing exceptions I do this:
let allCorrect = true;
try {
await check();
} catch(err) {
allCorrect = false;
}
expect(allCorrect).toBe(true);
Is it possible to do something like this?
expect(async () => await check()).not.toThrow()
We came across this with @kentaromiura today.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 102
- Comments: 53 (15 by maintainers)
I’d like to cast my vote for this api:
I like it because it’s simple and explicit.
You can just write:
await expect(asyncFunc()).rejects.toThrowError(TypeOfError);
Fixed with #3068. This will land in Jest v20.
@alfonsodev Maybe a slightly safer temporary solution would be:
@piuccio Try
await
-ing yourexpect
, eventually.None of the suggestions above were working for me so I ended up doing:
@cpojer I gave this a try and it appears to be more work than expected, and a consequent evolution of the way
expect
is used. If expect.toThrow was made compatible with promises, then people would have to use it this way:But once you make expect.toThrow compatible with promises, you’ll have a hard time justifying not making all matchers compatible with promises. And that’s a lot of work and added complexity when our initial problem was this try+await+catch block. It might be better to add a
syncify
util to jest that would allow writing such tests:The
syncify
implementation is trivial:Let me know if this idea makes sense to you.
I totally agree we should have this.
@Blutude Your async function does return something: it’s a promise resolving to
undefined
.https://github.com/facebook/jest/issues/1377#issuecomment-396232412 https://github.com/facebook/jest/issues/1377#issuecomment-473922360 https://jestjs.io/docs/en/expect#rejects
Personally, it’s not my favorite approach, someone not knowing the
expect.sync()
function has no way to understand what it does.I prefer explicit support of promises in
expect
:FWIW, I needed to test whether or not
async
functions threw in jest, so along with thesyncify
function, I wrote this little helper:So that I can write tests like:
Any status on this?
no, please don’t.
async/await
compiles into a promise. This is literally just like the work you did forpit
:when the function is called and returns a promise and it doesn’t throw, we should wait for the promise to resolve and then make sure it throws.
Since it creates an
async
function inside of anotherasync
function it should properly make theit
callback a promise, right?That does not work because your tests will be green even when no error is thrown (because then the catch won’t be triggered and no expectations will be run. No expectations are also green)
Here are the docs for it: https://facebook.github.io/jest/docs/expect.html#rejects
Here is how I would see the ideal
expect
. Comments are welcome 😃(I put this in a Gist to avoid cluttering this thread)
/cc @cpojer
Why can’t Jest detect if a promise was returned in a
toThrow
function and add it to a queue that will block the test from completing until it resolves? Or add a new expectation liketoResolve
ortoReject
, this would make it explicit that the expectation should beawait
ed.Up until Jest 22 this used to work
As of Jest 23+ it now says
Is the change intended?
Thanks @SimenB, I didn’t know about this lib, I’m keeping it close in case I need it.
@odelucca For me the best way for now is
rejectionOf
that I posted in this comment:What about
await expect(...).not.toThrow()
? Which is what the original question was about. My async function does not return anything so I cannot useawait expect(...).resolves...
@LukasBombach isn’t
expect.assertions(2)
used for this very reason?another temporary solution i have used
jasmine.fail
, which looks pretty idiomatic, although its not part of my eslint preset. So I must add// eslint-disable-line
Would you like to weigh in @cpojer on the proposals made thus far to see if one could be implemented?
This is an issue that I keep stumbling on when testing async code, would be great if a solution gets added to jest in the short run!
I really like your proposal for a
syncify
function @louisremi!I have simplified it a bit (together with your helper function @cowboy) and came up with:
A
sync
util could then be added toexpect
. This can then be used as follows:Or in shortened syntax:
What do you guys think?
This proposal is indeed quite nice to test an async function but it requires some boilerplate when all you need to test is a promise.
Currently it’s easy to test whether a promise resolve by simply
await
-ing for it but it’s harder (or verbose) to test that a promise reject.This could be mitigated by using a helper function which would swap the resolution/rejection of the promise:
But it may be better to make
expect()
return a promise-like value and to add atoResolve()
andtoReject()
matchers/modifiers:Small digression: this example also leads me to think that some matchers are missing, e.g. there are currently no ways to test an error without using
toThrowError()
. I think it would be nice to add atoBeAnError()
matcher and maketoThrow()
chainable:Ahhh! I did not see that! Thank you!
Thanks for coming up with a few proposals, everyone. I added some more thoughts in the PR by @excitement-engineer: https://github.com/facebook/jest/pull/3068#issuecomment-285070025
@excitement-engineer good catch! (pun totally intended)
throwing inside a try block is usually an eslint faux pas, but i think we can make an exception here. Put a nice random string in there so folks can’t accidentally run
-u
without looking at their snapshots 😄Maybe I’m taking crazy pills, but this seems to work just fine, no API change needed:
It’s 1 line, it’s expressive, it’s useable today. That said, if someone wanted to write a PR…
That’s kinda strange @excitement-engineer to have an
expect
in anotherexpect
. I would prefer @julien-f 's solution, but maybe a compromise is possible like Jasmine’sdone.fail()
method:I don’t think
jest.sincify
is a great name. It should live somewhere onexpect
possibly and be in the jest-matchers package.