В процессе тестирования приложений с использованием фреймворка Jasmine необходимо уделить внимание не только корректным, но и некорректным путям выполнения программы, таким как обработка ошибок. Ошибки могут быть связаны с различными факторами, включая неправильный ввод данных, сбои внешних сервисов, ошибки при асинхронных операциях и прочее. Тестирование таких случаев важно для обеспечения надежности и устойчивости к сбоям. Jasmine предоставляет несколько методов для тестирования обработки ошибок, как синхронных, так и асинхронных.
Для тестирования синхронных ошибок необходимо использовать метод
toThrow(). Этот метод позволяет проверить, выбрасывает ли
код ожидаемую ошибку в процессе выполнения.
describe('Тестирование синхронных ошибок', () => {
it('должен выбросить ошибку при некорректном значении', () => {
function throwError() {
throw new Error('Некорректное значение');
}
expect(throwError).toThrowError('Некорректное значение');
});
});
В этом примере создается функция throwError(), которая
выбрасывает ошибку с сообщением «Некорректное значение». Тест проверяет,
что при вызове этой функции будет выброшена именно такая ошибка.
Метод toThrow() позволяет также проверять тип ошибки.
Например:
describe('Тестирование синхронных ошибок', () => {
it('должен выбросить ошибку типа TypeError', () => {
function throwError() {
throw new TypeError('Тип ошибки неправильный');
}
expect(throwError).toThrowError(TypeError);
});
});
Здесь тест проверяет, что выбрасываемая ошибка является экземпляром
TypeError.
Jasmine также позволяет проверять ошибки с помощью регулярных выражений, что полезно, когда важно только сообщение об ошибке, но не его точное содержание.
describe('Тестирование синхронных ошибок', () => {
it('должен выбросить ошибку с сообщением, содержащим некорректный ввод', () => {
function throwError() {
throw new Error('Некорректный ввод данных');
}
expect(throwError).toThrowError(/Некорректный ввод/);
});
});
В этом примере тест проверяет, что сообщение об ошибке содержит строку «Некорректный ввод», но не обязательно совпадает полностью.
При тестировании асинхронных операций, таких как запросы к серверу
или таймеры, ошибки могут возникать позже, чем код выполнения теста. Для
обработки таких ошибок Jasmine предоставляет несколько инструментов,
включая done() для выполнения асинхронных тестов и
async/await для работы с промисами.
done() для асинхронных ошибокВ случае использования асинхронных операций в тестах, когда
необходимо дождаться завершения операции перед утверждениями, можно
использовать функцию done(). Эта функция уведомляет Jasmine
о завершении асинхронного теста.
describe('Тестирование асинхронных ошибок', () => {
it('должен выбросить ошибку при отказе в запросе', (done) => {
function makeRequest(callback) {
setTimeout(() => {
callback(new Error('Ошибка при запросе'));
}, 100);
}
makeRequest((error) => {
expect(error).toBeInstanceOf(Error);
expect(error.message).toBe('Ошибка при запросе');
done();
});
});
});
В этом примере создается асинхронная функция
makeRequest, которая симулирует ошибку через таймер. После
завершения асинхронной операции вызывается метод done(),
чтобы уведомить Jasmine о завершении теста.
async/awaitСовременные подходы к асинхронному тестированию часто включают
использование async и await для работы с
промисами, что делает код более читаемым и удобным для понимания.
describe('Тестирование асинхронных ошибок с async/await', () => {
it('должен выбросить ошибку при отказе в запросе', async () => {
function makeRequest() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Ошибка при запросе'));
}, 100);
});
}
try {
await makeRequest();
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error.message).toBe('Ошибка при запросе');
}
});
});
Здесь используется промис для асинхронной операции, и через
await дожидаемся его завершения. Если ошибка возникает, она
перехватывается в блоке catch, и далее выполняются
утверждения.
Промисы — это частый источник ошибок в асинхронном коде. Чтобы
проверить, правильно ли обрабатываются ошибки в промисах, можно
использовать методы catch и reject.
describe('Тестирование ошибок в промисах', () => {
it('должен выбросить ошибку при отклонении промиса', async () => {
function makeRequest() {
return Promise.reject(new Error('Ошибка при запросе'));
}
await expectAsync(makeRequest()).toBeRejectedWithError('Ошибка при запросе');
});
});
В этом примере тестируется промис, который отклоняется с ошибкой.
Метод expectAsync() позволяет тестировать промисы и
проверять, что они отклоняются с ожидаемой ошибкой.
Иногда тестирование обработки ошибок может включать интеграцию с
другими библиотеками, такими как fetch для HTTP-запросов
или сторонними API. В таких случаях важно правильно мокировать
зависимости, чтобы тесты не зависели от реальных внешних факторов.
Для тестирования кода, который зависит от внешнего API, можно
использовать моки и шпионы. Например, с использованием
spyOn можно подменить функцию fetch и
эмулировать ошибку при запросе.
describe('Тестирование HTTP-запросов с мокированием', () => {
it('должен выбросить ошибку при неудачном запросе', async () => {
spyOn(window, 'fetch').and.returnValue(Promise.reject(new Error('Ошибка запроса')));
try {
await fetch('https://example.com/data');
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error.message).toBe('Ошибка запроса');
}
});
});
Здесь с помощью spyOn мы подменяем реализацию
fetch, чтобы она всегда отклонялась с ошибкой. Это
позволяет тестировать логику обработки ошибок без необходимости
совершать реальные сетевые запросы.
Тестирование обработки ошибок — важная часть тестирования устойчивости и надежности приложения. Jasmine предоставляет богатый набор инструментов для тестирования ошибок как в синхронном, так и в асинхронном коде. Правильная обработка ошибок в тестах позволяет уверенно выявлять и устранять потенциальные сбои в программном обеспечении.