BACK
Use casesCleanup test — verifying unsubscribe
Use cases · 67

Cleanup test — verifying unsubscribe

Pattern

Memory leaks often don't show up in ordinary tests — they check values but not teardown. interval/socket/WebSocket can keep running after a component's destroy, and the test won't notice. A cleanup test explicitly proves: "after destroy, the stream is completed".

The problem it solves

HTTP requests complete on their own, so HTTP tests never leak. But interval, fromEvent, WebSocket, valueChanges are forever. Forget takeUntilDestroyed and a value-based test still passes while the leak remains.

Operators and why they matter

  • takeUntil(destroy$) — ties the source to the destroy signal. This is what we're testing.
  • finalize(() => log('teardown')) — gives us a way to assert that teardown happened.
  • interval — simulates a never-ending source in the test.

Gotchas

  • A value-only test ("received X ticks") does NOT prove cleanup. Without a finalize/teardown assert, leaks are invisible.
  • Don't leave an interval in a test without take or takeUntil. The suite hangs or fails with a timeout.
  • HTTP one-shot tests don't cover cleanup for long-lived streams. Different scenarios.

What you get

The test explicitly verifies: the stream completes on destroy and emits nothing more after. Leaks become visible.

script.ts // TypeScript
CONSOLE · Console output
Hit Run to see the result...