javascript / intermediate
Snippet
Testing Asynchronous Debounced Composables Using Fake Timers in Vitest
Unit testing composables that depend on setTimeout or asynchronous debounce mechanisms requires controlling time deterministically. Using Vitest fake timers (vi.useFakeTimers and vi.advanceTimersByTime) allows verifying intermediate and final reactive states across precise millisecond thresholds without adding real delays to the test suite.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';import { ref } from 'vue';import { useDebouncedFilter } from './useDebouncedFilter';describe('useDebouncedFilter', () => {beforeEach(() => {vi.useFakeTimers();});afterEach(() => {vi.restoreAllMocks();});it('delays updating filter output until debounce delay elapses', () => {const source = ref('initial');const { debouncedValue } = useDebouncedFilter(source, 300);expect(debouncedValue.value).toBe('initial');source.value = 'updated-query';expect(debouncedValue.value).toBe('initial');vi.advanceTimersByTime(299);expect(debouncedValue.value).toBe('initial');vi.advanceTimersByTime(1);expect(debouncedValue.value).toBe('updated-query');});});
vue
Breakdown
1
vi.useFakeTimers();
Replaces the global JavaScript timer functions with synchronous mock implementations.
2
source.value = 'updated-query';
Mutates the reactive ref to trigger the internal debounce timer within the composable.
3
vi.advanceTimersByTime(1);
Simulates exact elapsed time to complete the 300ms window and trigger the reactive update.