Как обработать состояние rejected в Promise при тестировании?

«Как обработать состояние rejected в Promise при тестировании?» — вопрос из категории JavaScript, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

При тестировании асинхронного кода на JavaScript (например, с Jest, Mocha, Jasmine) важно корректно проверять, что промис переходит в состояние rejected. Использование async/await вместе с утверждениями (assertions) фреймворка — самый чистый способ.

1. Проверка rejected промиса с async/await и assert.rejects (Jest/Node.js assert):

// Jest
it('should reject the promise on invalid input', async () => {
    await expect(asyncFunctionThatRejects('invalid')).rejects.toThrow('Invalid input error');
});

// Или с использованием try-catch для более сложной логики проверки
it('should reject with specific error type', async () => {
    try {
        await asyncFunctionThatRejects();
        // Если выполнение дошло сюда, промис НЕ был rejected — это ошибка теста
        fail('Promise should have been rejected'); // Jest
        // или throw new Error('Promise should have been rejected');
    } catch (error) {
        // Проверяем детали ошибки
        expect(error).toBeInstanceOf(ValidationError);
        expect(error.message).toContain('Invalid data');
    }
});

2. Использование .catch() в цепочке промисов (более старый стиль):

it('should handle rejected promise', () => {
    // Важно: возвращаем промис из теста
    return asyncFunctionThatRejects()
        .then(() => {
            // Если этот then выполнился, тест должен упасть
            throw new Error('Expected promise to be rejected');
        })
        .catch((error) => {
            expect(error.message).toBe('Expected error');
        });
});

3. Проверка в тестах UI (например, с Cypress):

// Cypress автоматически обрабатывает промисы, но можно проверить вызов, который должен завершиться ошибкой
cy.intercept('POST', '/api/data').as('postData');
cy.get('button.submit').click();
cy.wait('@postData').its('response.statusCode').should('eq', 500); // Ждем rejected запрос

Ключевой момент для QA: Тесты должны не только обрабатывать rejected состояния, чтобы не падать, но и намеренно проверять, что код приложения корректно отвергает промисы при ошибочных сценариях. Это часть негативного тестирования.