Memory leaks часто не видны в обычных тестах — они проверяют значения, но не проверяют teardown. interval/socket/WebSocket могут продолжать работать после destroy компонента, и тест об этом не узнает. Cleanup test явно доказывает: «после destroy stream завершён».
Какую проблему решаем
HTTP-запросы complete сами, поэтому утечек в HTTP-тестах не бывает. Но interval, fromEvent, WebSocket, valueChanges — вечные. Если забыли takeUntilDestroyed — тест по значениям всё равно пройдёт, а утечка останется.
Операторы и зачем они нужны
takeUntil(destroy$) — связывает source с destroy signal. Это то, что мы тестируем.
finalize(() => log('teardown')) — даёт нам способ ассертить факт teardown.
interval — симулирует never-ending source в тесте.
Подводные камни
Тест только по значениям («получил X tick») НЕ доказывает cleanup. Без finalize/assert на teardown — утечки невидимы.
Не оставляйте interval в тесте без take или takeUntil. Suite зависнет или upalt c таймаутом.
HTTP one-shot тесты не покрывают cleanup для long-lived streams. Это разные сценарии.
Что в итоге получаем
Тест явно проверяет: stream завершается при destroy и не эмитит больше после. Утечки становятся видимыми.