Mocking isolates your tests from external dependencies like APIs, modules, and timers.
vi.fn() - Mock Functions
typescriptimport { describe, it, expect, vi } from 'vitest' describe('Mock Functions', () => { it('tracks calls', () => { const mockFn = vi.fn() mockFn('arg1', 'arg2') mockFn('arg3') expect(mockFn).toHaveBeenCalled() expect(mockFn).toHaveBeenCalledTimes(2) expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2') expect(mockFn).toHaveBeenLastCalledWith('arg3') }) it('returns values', () => { const mockFn = vi.fn() .mockReturnValue('default') .mockReturnValueOnce('first') .mockReturnValueOnce('second') expect(mockFn()).toBe('first') expect(mockFn()).toBe('second') expect(mockFn()).toBe('default') }) it('implements custom behavior', () => { const mockFn = vi.fn((x: number) => x * 2) expect(mockFn(5)).toBe(10) }) })
vi.spyOn() - Spy on Methods
typescriptimport { vi } from 'vitest' import * as utils from './utils' describe('Spying', () => { it('spies on method', () => { const spy = vi.spyOn(utils, 'formatDate') utils.formatDate(new Date()) expect(spy).toHaveBeenCalled() spy.mockRestore() // Restore original }) it('mocks implementation', () => { const spy = vi.spyOn(console, 'log').mockImplementation(() => {}) console.log('test') // Doesn't actually log expect(spy).toHaveBeenCalledWith('test') spy.mockRestore() }) })
vi.mock() - Mock Modules
typescriptimport { vi } from 'vitest' // Mock entire module vi.mock('./api', () => ({ fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'Test' }), fetchPosts: vi.fn().mockResolvedValue([]) })) import { fetchUser } from './api' // Now mocked describe('With mocked API', () => { it('uses mock', async () => { const user = await fetchUser(1) expect(user.name).toBe('Test') }) })
Mocking fetch
typescriptimport { vi, beforeEach } from 'vitest' describe('API calls', () => { beforeEach(() => { // Mock global fetch global.fetch = vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({ data: 'test' }) }) }) it('fetches data', async () => { const response = await fetch('/api/data') const data = await response.json() expect(data).toEqual({ data: 'test' }) expect(fetch).toHaveBeenCalledWith('/api/data') }) })
Mocking Timers
typescriptimport { vi, beforeEach, afterEach } from 'vitest' describe('Timers', () => { beforeEach(() => { vi.useFakeTimers() }) afterEach(() => { vi.useRealTimers() }) it('handles setTimeout', () => { const callback = vi.fn() setTimeout(callback, 1000) expect(callback).not.toHaveBeenCalled() vi.advanceTimersByTime(1000) expect(callback).toHaveBeenCalled() }) it('handles setInterval', () => { const callback = vi.fn() setInterval(callback, 100) vi.advanceTimersByTime(350) expect(callback).toHaveBeenCalledTimes(3) }) it('runs all timers', () => { const callback = vi.fn() setTimeout(callback, 5000) vi.runAllTimers() expect(callback).toHaveBeenCalled() }) })
Mocking in Vue Components
typescriptimport { mount } from '@vue/test-utils' import { vi } from 'vitest' import UserProfile from './UserProfile.vue' import * as api from '@/api' vi.mock('@/api') describe('UserProfile', () => { it('loads user data', async () => { vi.mocked(api.fetchUser).mockResolvedValue({ id: 1, name: 'Alice' }) const wrapper = mount(UserProfile, { props: { userId: 1 } }) await flushPromises() expect(api.fetchUser).toHaveBeenCalledWith(1) expect(wrapper.text()).toContain('Alice') }) })
Clearing Mocks
typescriptafterEach(() => { vi.clearAllMocks() // Clear call history vi.resetAllMocks() // Clear + reset implementations vi.restoreAllMocks() // Restore original implementations })