BACK
Use casesMarble test retry — time without real timers
Use cases · 66

Marble test retry — time without real timers

Pattern

Retry with backoff can take 1, 2, 4 seconds between attempts. Testing with real timers means a multi-second test suite. Virtual time from the TestScheduler lets you verify the ENTIRE retry logic instantly.

The problem it solves

Large jasmine timeouts slow the suite down and give no guarantee — on a slow CI it can still flake. Plus: you need to verify the exact sequence (1 → 2 → 4 seconds), not just "got a result after a few seconds".

Operators and why they matter

  • TestScheduler — replaces real timers with virtual frames. scheduler.flush() fast-forwards virtual time.
  • The retry marble captures error notifications, delay frames, and the moments of resubscribe.
  • Expected marble — the final success or fallback frame.

Gotchas

  • You can't reliably test backoff with setTimeout and a jasmine 10s timeout. On CI it'll fail sooner or later.
  • If the scheduler is "baked in" inside the function (a literal timer()), virtual time won't hook in. Make the scheduler a parameter or a dependency.
  • Verify the retry condition: a 400 shouldn't wait for backoff like a 500. Those are different code paths.

What you get

The retry policy is verified fast, precisely, and without any real waiting. The test suite stays in milliseconds.

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