Jasmine предоставляет мощные средства для тестирования асинхронного
кода в JavaScript. Современный подход основан на использовании
async/await, который позволяет писать асинхронные тесты так
же читаемо, как синхронный код, без необходимости вручную управлять
колбэками или промисами через done().
Любая функция, помеченная как async, автоматически
возвращает промис. Это открывает возможность использовать
await для ожидания результата асинхронной операции. В
Jasmine асинхронный тест можно объявить следующим образом:
it('должен получить данные с сервера', async () => {
const data = await fetchData();
expect(data).toBeDefined();
expect(data.length).toBeGreaterThan(0);
});
Ключевые моменты:
async перед функцией теста сообщает Jasmine, что она
асинхронная.await приостанавливает выполнение теста до завершения
промиса.async функции, автоматически
приводят к провалу теста.beforeEach и afterEachДля подготовки или очистки состояния перед или после тестов также
допустимо использовать async/await. Например, загрузка
тестовых данных перед каждым тестом:
beforeEach(async () => {
await initializeDatabase();
});
afterEach(async () => {
await clearDatabase();
});
Особенности:
beforeEach и afterEach.awaitИногда удобнее возвращать промис напрямую без использования
async/await:
it('должен завершиться после промиса', () => {
return fetchData().then(data => {
expect(data).toBeDefined();
});
});
Однако использование async/await повышает читаемость,
особенно при сложных цепочках асинхронных вызовов.
expectAsyncJasmine предоставляет специальный набор функций для асинхронных
проверок через expectAsync. Это особенно полезно для
проверки промисов на успешное выполнение или отклонение:
it('должен успешно завершить промис', async () => {
await expectAsync(fetchData()).toBeResolved();
});
it('должен отклонить промис', async () => {
await expectAsync(fetchWithError()).toBeRejected();
});
it('должен отклонить промис с конкретной ошибкой', async () => {
await expectAsync(fetchWithError()).toBeRejectedWithError('Network Error');
});
Примечания:
expectAsync работает только с промисами или
асинхронными функциями.toBeResolved, toBeRejected,
toBeRejectedWithError позволяют писать компактные проверки
без использования .then или .catch.По умолчанию Jasmine ожидает завершения асинхронного теста в течение 5 секунд. Этот лимит можно изменить глобально или для конкретного теста:
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; // глобально
it('долго выполняющийся тест', async () => {
await longRunningTask();
}, 15000); // тайм-аут конкретного теста
Важно устанавливать тайм-ауты, превышающие время выполнения асинхронной операции, иначе тест может завершиться с ошибкой.
В одном it можно использовать как синхронные, так и
асинхронные проверки:
it('сочетание sync и async проверок', async () => {
const initialValue = getValueSync();
expect(initialValue).toBe(10);
const asyncResult = await fetchData();
expect(asyncResult).toContain('success');
});
Это позволяет разделять тест на логические части, не создавая излишней сложности.
Асинхронные ошибки, выброшенные внутри async функции,
автоматически регистрируются Jasmine. Нет необходимости оборачивать код
в try/catch, если цель — провал теста при ошибке:
it('тест завершится с ошибкой при исключении', async () => {
await asyncFunctionThatThrows();
// Если функция выбросит исключение, тест провалится автоматически
});
Для тестирования конкретных ошибок применяется
expectAsync(...).toBeRejectedWithError.
async/await вместо
done(), если есть возможность. Это делает код чище
и предотвращает забытые вызовы done().beforeEach) и
проверку результатов (it). Асинхронная подготовка
упрощает поддержку тестов.expectAsync для промисов.
Это избавляет от цепочек .then/.catch и повышает
читаемость.async функции автоматически приводит к провалу теста, что
упрощает выявление проблем.Асинхронные возможности Jasmine с async/await позволяют
писать чистые, понятные и надежные тесты, которые легко поддерживать
даже при сложной логике взаимодействия с сервером, базой данных или
сторонними сервисами.