Тестирование асинхронного кода в Angular требует понимания того, как работают Promises, Observables и таймеры. Основная цель — корректно ожидать завершение асинхронной операции перед проверкой результатов.
async и
fakeAsyncasync/await Позволяет писать тесты, которые выглядят синхронно, но ожидают завершения асинхронных операций:
it('должен получить данные', async () => {
const data = await service.getData().toPromise();
expect(data).toBeTruthy();
});fakeAsync и tick Используется для имитации времени и управления таймерами внутри тестов:
import { fakeAsync, tick } from '@angular/core/testing';
it('должен работать с таймером', fakeAsync(() => {
let value = false;
setTimeout(() => value = true, 1000);
tick(1000);
expect(value).toBeTrue();
}));
Метод tick() позволяет мгновенно продвинуть виртуальное
время на заданное количество миллисекунд, что исключает задержки во
время выполнения тестов.
Для Observables часто используют оператор subscribe в
сочетании с done или fakeAsync:
it('должен получать значения из Observable', (done) => {
service.getObservableData().subscribe(value => {
expect(value).toBe(42);
done();
});
});
Использование done гарантирует, что тест завершится
только после получения данных.
TestSchedulerTestScheduler из RxJS позволяет точно управлять временем
эмиссий событий:
import { TestScheduler } from 'rxjs/testing';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
const scheduler = new TestScheduler((actual, expected) => {
expect(actual).toEqual(expected);
});
scheduler.run(({ expectObservable }) => {
const source$ = of('a').pipe(delay(10, scheduler));
expectObservable(source$).toBe('10ms a');
});
Это особенно полезно для сложных потоков данных, где важно предсказуемое поведение теста без зависимости от реального времени.
Асинхронные тесты должны учитывать возможные ошибки и таймауты:
it('должен обработать ошибку', async () => {
await expectAsync(service.getErrorData()).toBeRejectedWithError('Ошибка сервера');
});
Метод expectAsync позволяет проверять правильность
обработки исключений, что обеспечивает надежность приложения при
нестандартных ситуациях.