An Async Example
Во-первых включите поддержку Babel в Jest, как описано в руководстве Приступая к работе.
Давайте создадим простой модуль, который извлекает данные пользователя из API и возвращает имя пользователя.
// user.js import request from './request'; export function getUserName(userID) { return request('/users/' + userID).then(user => user.name); }
В реализации выше мы ожидаем, что модуль request.js
вернет отложенное значение. Мы создаем цепь вызовов из then
чтобы извлечь имя пользователя.
Теперь представьте себе реализацию request.js
, которая обращается к сети и получает некоторые пользовательские данные:
// request.js const http = require('http'); export default function request(url) { return new Promise(resolve => { // Пример HTTP запроса, к примеру для извлечения // данных пользователя из API. // Для данного модуля используется мок из __mocks__/request.js http.get({path: url}, response => { let data = ''; response.on('data', _data => data += _data); response.on('end', () => resolve(data)); }); }); }
Из-за того что мы не хотим обращаться к сети в нашем тесте, мы вручную создадим мок для нашего модуля request.js
в папке __mocks__
. Он может выглядеть примерно так:
// __mocks__/request.js const users = { 4: {name: 'Вася'}, 5: {name: 'Петя'}, }; export default function request(url) { return new Promise((resolve, reject) => { const userID = parseInt(url.substr('/users/'.length), 10); process.nextTick( () => users[userID] ? resolve(users[userID]) : reject({ error: 'Пользовтаель ' + userID + ' не найден.', }) ); }); }
Now let's write a test for our async functionality.
// __tests__/user-test.js jest.mock('../request'); import * as user from '../user'; // The assertion for a promise must be returned. it('works with promises', () => { expect.assertions(1); return user.getUserName(4).then(data => expect(data).toEqual('Mark')); });
Мы вызываем jest.mock('../request')
, чтобы указать Jest использовать наш вручную заданный мок. it
ожидает, что возвращаемое значение будет промисом, который в итоге будет разрешен. Можно задать цепочку любого размера из промисов и вызвать expect
в любой момент, до тех пор, пока вы возвращаете промис.
.resolves
#
доступно в версиях Jest 20.0.0+ #
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.
it('works with resolves', () => { expect.assertions(1); return expect(user.getUserName(5)).resolves.toEqual('Paul'); });
async
/await
#
Writing tests using the async
/await
syntax is easy. Here is how you'd write the same examples from before:
// async/await can be used. it('works with async/await', async () => { expect.assertions(1); const data = await user.getUserName(4); expect(data).toEqual('Mark'); }); // async/await can also be used with `.resolves`. it('works with async/await and resolves', async () => { expect.assertions(1); await expect(user.getUserName(5)).resolves.toEqual('Paul'); });
Чтобы сделать async/await доступными в вашем проекте, установите babel-preset-env
и включите функцию в файле .babelrc
.
Обработка ошибок #
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:
// Testing for async errors using Promise.catch. test('tests error with promises', async () => { expect.assertions(1); return user.getUserName(2).catch(e => expect(e).toEqual({ error: 'User with 2 not found.', }) ); }); // Or using async/await. it('tests error with async/await', async () => { expect.assertions(1); try { await user.getUserName(1); } catch (e) { expect(e).toEqual({ error: 'User with 1 not found.', }); } });
.rejects
#
доступно в версиях Jest 20.0.0+ #
The.rejects
helper works like the .resolves
helper. If the promise is fulfilled, the test will automatically fail.
// 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.', }); });
Код для этого примера доступен в examples/async.
Если вы хотите протестировать такие таймеры, как setTimeout
, взгляните на моки для таймеров.