In jest, there are a couple of different ways to handle tests which deal with async code.
Let's say way have a test that calls fetchSomeAsyncThing()
.
it('should call my api', () => {
const result = fetchSomeAsyncThing();
expect(result.foo).toBe('hello world')
});
This will fail.
Why?
Because of the way JavaScript handles async code.
When you call a function known to be async, whether it's something that returns a Promise
, calls a setTimeout
, etc, that function get pushed onto a call stack, and called wayyy after your tests have actually ran.
A stack is a data structure kinda like an array which basically means, the last thing that got put into it, is the first thing to come out. Read more about stacks and async Javacript.
Use the done callback
If your async function returns a callback, several of the jest functions provide a done callback which you can use like this...
it('should call my api', (done) => {
const result = fetchSomeAsyncThing((result) => {
expect(result.foo).toBe('hello world');
done();
});
});
As you can see, the callback to the it
method above returns a done
function.
This done
function will tell jest that your async method is done and it will wait for that all to finish before wrapping up that test.
Use promises
If your async function returns promises you can do one of 2 things.
it('should call my api', (done) => {
const result = fetchSomeAsyncThing().then((result) => {
expect(result.foo).toBe('hello world');
done();
});
});
Similar to above, use the done
function inside the .then
.
Or, you can simply return the entire promise.
it('should call my api', () => {
return fetchSomeAsyncThing((result) => {
expect(result.foo).toBe('hello world');
});
});
In this case, jest will realize that the return value of the test was itself a promise, and will therefore wait until that promise fully resolves before wrapping up the test.
Use async / await
Once again, if you know that your async function returns a promise, you can use the async
and await
features of modern Javascript.
it('should call my api', async () => {
const result = await fetchSomeAsyncThing();
expect(result.foo).toBe('hello world');
});
The async
/ await
method is a nice, clean way to read the code.
Top comments (0)