How to Use fakeAsync in Angular Test for Async Code
Use
fakeAsync to wrap your Angular test function to simulate asynchronous passage of time synchronously. Inside it, use tick() to advance virtual time and trigger async operations like timers or promises immediately.Syntax
The fakeAsync function wraps a test function to run it in a special fake asynchronous zone. Inside this zone, asynchronous tasks like setTimeout or Promise are controlled synchronously.
The tick() function moves the virtual clock forward by a specified number of milliseconds, causing any pending timers or async tasks scheduled for that time to execute immediately.
typescript
import { fakeAsync, tick } from '@angular/core/testing'; describe('Test Suite', () => { it('should test async code synchronously', fakeAsync(() => { let done = false; setTimeout(() => { done = true; }, 1000); expect(done).toBe(false); tick(1000); // Move time forward by 1000ms expect(done).toBe(true); })); });
Example
This example shows how fakeAsync and tick() let you test code with setTimeout without waiting in real time. The test checks a flag before and after advancing time.
typescript
import { fakeAsync, tick } from '@angular/core/testing'; describe('fakeAsync Example', () => { it('should update value after timeout', fakeAsync(() => { let value = 0; setTimeout(() => { value = 42; }, 500); expect(value).toBe(0); // Before tick tick(500); // Advance time by 500ms expect(value).toBe(42); // After tick })); });
Output
Test passes with value updated after tick
Common Pitfalls
- Not wrapping the test function with
fakeAsynccausestick()to fail. - Forgetting to call
tick()means async code insidesetTimeoutorPromisewon’t run during the test. - Using
fakeAsyncwith real asynchronous operations like HTTP requests won’t work; useasyncandwhenStable()instead.
typescript
/* Wrong way: tick() used outside fakeAsync */ it('wrong test', () => { let done = false; setTimeout(() => done = true, 1000); tick(1000); // Error: tick() can only be called in fakeAsync zone }); /* Right way: */ it('right test', fakeAsync(() => { let done = false; setTimeout(() => done = true, 1000); tick(1000); expect(done).toBe(true); }));
Quick Reference
| Function | Purpose |
|---|---|
| fakeAsync(() => {...}) | Wraps test to run async code synchronously |
| tick(milliseconds?) | Advances virtual time by given ms, runs timers |
| flush() | Runs all pending timers until none remain |
| discardPeriodicTasks() | Clears any periodic timers like setInterval |
Key Takeaways
Wrap your test function with fakeAsync to control async code synchronously.
Use tick() to simulate the passage of time and trigger timers immediately.
Do not use fakeAsync for real HTTP calls; prefer async and whenStable instead.
Always call tick() after scheduling async tasks to test their effects.
Remember to discard periodic timers to avoid test leaks.