В Jasmine done используется для тестирования
асинхронного кода, когда выполнение теста зависит от
завершения операций, выполняемых с задержкой, например, сетевых
запросов, таймеров или промисов. Без правильного использования
done тест может завершиться раньше времени, что приведет к
ложноположительным или ложоотрицательным результатам.
donedone — это функция, которую Jasmine предоставляет как
аргумент в it или
beforeEach/afterEach. Передача
done в функцию теста сообщает Jasmine, что тест
асинхронный, и завершение теста должно ожидать вызова
этой функции.
Пример базового использования:
it('асинхронный тест с setTimeout', function(done) {
let value = false;
setTimeout(function() {
value = true;
expect(value).toBe(true);
done(); // сигнализируем Jasmine о завершении теста
}, 1000);
});
В этом примере тест не будет считаться завершенным, пока не будет
вызван done(). Если done() не будет вызван,
тест упадет с таймаутом, который по умолчанию равен 5
секунд.
done
с промисамиХотя Jasmine поддерживает возвращение промисов напрямую,
done иногда используется для более сложного контроля над
асинхронными операциями.
it('тест с промисом', function(done) {
fetchDataFromServer()
.then(function(data) {
expect(data).toBeDefined();
done();
})
.catch(function(error) {
done.fail(error); // сообщает Jasmine о неуспешном завершении
});
});
Метод done.fail() позволяет правильно
обрабатывать ошибки асинхронного кода, предотвращая
ложноположительные результаты тестов.
done в хуках
beforeEach и afterEachПараметр done можно использовать не только в тестах, но
и в хуках, чтобы подготовка или очистка выполнялись асинхронно:
beforeEach(function(done) {
initializeDatabase(function() {
done();
});
});
afterEach(function(done) {
cleanupDatabase(function() {
done();
});
});
Это особенно важно при работе с базами данных, сетевыми сервисами и другими ресурсами, требующими асинхронной инициализации.
done — если функция
done() вызывается более одного раза, Jasmine выбрасывает
ошибку. Это часто случается при использовании таймеров или промисов с
несколькими ветвями.done — если забыть вызвать
done(), тест упадет по таймауту. Для уменьшения вероятности
ошибки рекомендуется всегда использовать return с
промисами, если они поддерживаются.done — лучше
использовать один подход. Если функция возвращает промис, можно обойтись
без done. Пример корректного использования без
done:it('тест с возвращением промиса', function() {
return fetchDataFromServer().then(function(data) {
expect(data).toBeDefined();
});
});
done() для любых колбэков, таймеров,
событий или асинхронных функций, которые не возвращают промис.done.fail(error), чтобы тест корректно падал при
исключениях.done() вызывается точно один
раз и только после завершения всех асинхронных операций.async/await предпочтительнее
возвращать промис или использовать async функцию, избегая
лишнего done.it('комбинированный асинхронный тест', function(done) {
let counter = 0;
setTimeout(function() {
counter += 1;
fetchDataFromServer().then(function(data) {
counter += 1;
expect(counter).toBe(2);
expect(data).toBeDefined();
done();
}).catch(done.fail);
}, 500);
});
В этом примере несколько асинхронных операций объединены: сначала
таймер, затем промис. done() вызывается только после
завершения всех шагов, что обеспечивает правильную
последовательность проверок.
Использование done обеспечивает точный контроль
над асинхронным тестированием в Jasmine и позволяет избегать
ошибок, связанных с преждевременным завершением тестов.