An Async Example
Let’s implement a module that fetches user data from an API and returns the user name.
user.js
In the above implementation, we expect the request.js
module to return a promise. We chain a call to then
to receive the user name.
Now imagine an implementation of request.js
that goes to the network and fetches some user data:
request.js
const http = require('http');
export default function request(url) {
return new Promise(resolve => {
// This is an example of an http request, for example to fetch
// user data from an API.
// This module is being mocked in __mocks__/request.js
http.get({path: url}, response => {
let data = '';
response.on('data', _data => (data += _data));
response.on('end', () => resolve(data));
});
});
__mocks__/request.js
Now let’s write a test for our async functionality.
__tests__/user-test.js
jest.mock('../request');
// The assertion for a promise must be returned.
it('works with promises', () => {
expect.assertions(1);
return user.getUserName(4).then(data => expect(data).toBe('Mark'));
});
We call jest.mock('../request')
to tell Jest to use our manual mock. it
expects the return value to be a Promise that is going to be resolved. You can chain as many Promises as you like and call expect
at any time, as long as you return a Promise at the end.
There is a less verbose way using resolves
to unwrap the value of a fulfilled promise together with any other matcher. If the promise is rejected, the assertion will fail.
// async/await can be used.
it('works with async/await', async () => {
expect.assertions(1);
const data = await user.getUserName(4);
expect(data).toBe('Mark');
});
// async/await can also be used with `.resolves`.
expect.assertions(1);
});
To enable async/await in your project, install @babel/preset-env and enable the feature in your babel.config.js
file.
Errors can be handled using the .catch
method. Make sure to add expect.assertions
to verify that a certain number of assertions are called. Otherwise a fulfilled promise would not fail the test:
The.rejects
helper works like the .resolves
helper. If the promise is fulfilled, the test will automatically fail. expect.assertions(number)
is not required but recommended to verify that a certain number of are called during a test. It is otherwise easy to forget to return
/await
the .resolves
assertions.
// Testing for async errors using `.rejects`.
it('tests error with rejects', () => {
expect.assertions(1);
return expect(user.getUserName(3)).rejects.toEqual({
error: 'User with 3 not found.',
});
});
// Or using async/await with `.rejects`.
it('tests error with async/await and rejects', async () => {
expect.assertions(1);
await expect(user.getUserName(3)).rejects.toEqual({
error: 'User with 3 not found.',
});
The code for this example is available at examples/async.
If you’d like to test timers, like setTimeout
, take a look at the documentation.