An Async Example
Во-первых включите поддержку Babel в Jest, как описано в руководстве Приступая к работе.
Давайте создадим модуль, который получает данные пользователя из API и возвращает имя пользователя.
// user.js
import request from './request';
export function getUserName(userID) {
return request('/users/' + userID).then(user => user.name);
}
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.
Теперь представим реализацию 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__
не сработает). Он может выглядеть примерно так:
// __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: 'Пользователь с ID ' + 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
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 also possible. 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
и включите эту функцию в файле babel.config.js
.
Обработка ошибок
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.
it('тестирует ошибки с использованием промисов', () => {
expect.assertions(1);
return user.getUserName(2).catch(e =>
expect(e).toEqual({
error: 'Пользователь с ID 2 не найден.',
}),
);
});
// Или используя 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
The.rejects
helper works like the .resolves
helper. If the promise is fulfilled, the test will automatically fail. expect.assertions(number)
не является обязательным, но рекомендуется для подтверждения точного числа проверок вызванных во время теста. В противном случае легко забыть return
/await
в проверках с использованием .resolves
.
// 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
, обратите внимание на документацию Timer mocks.