Vitest Cheatsheet
Mocking
Use this Vitest reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
vi.fn() — Mock Functions
import { vi, expect } from 'vitest' const mockFn = vi.fn() mockFn('arg1', 'arg2') expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2') expect(mockFn).toHaveBeenCalledTimes(1)
Return Value Control
| Method | Effect |
|---|---|
.mockReturnValue(val) | Always returns val |
.mockReturnValueOnce(val) | Returns val on next call, then resets |
.mockResolvedValue(val) | Returns Promise.resolve(val) |
.mockResolvedValueOnce(val) | One-time resolved promise |
.mockRejectedValue(err) | Returns Promise.reject(err) |
.mockRejectedValueOnce(err) | One-time rejected promise |
.mockImplementation(fn) | Replace implementation |
.mockImplementationOnce(fn) | One-time implementation |
.mockReturnThis() | Returns this (chaining) |
.mockName(name) | Set display name for error messages |
const fn = vi.fn() .mockReturnValueOnce('first') .mockReturnValueOnce('second') .mockReturnValue('default') fn() // 'first' fn() // 'second' fn() // 'default' fn() // 'default'
const asyncFn = vi.fn() .mockResolvedValueOnce({ id: 1 }) .mockRejectedValueOnce(new Error('network')) await asyncFn() // { id: 1 } await asyncFn() // throws Error('network')
Mocking Modules with vi.mock
// Hoist vi.mock calls — they run before imports import { describe, it, expect, vi } from 'vitest' import { fetchUser } from './api' vi.mock('./api', () => ({ fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'Alice' }), })) it('uses mocked fetchUser', async () => { const user = await fetchUser(1) expect(user.name).toBe('Alice') })
vi.mockis automatically hoisted aboveimportstatements. Do not put it insidedescribeoritblocks — it always applies module-wide.
Partial Module Mocking
vi.mock('./utils', async (importOriginal) => { const actual = await importOriginal<typeof import('./utils')>() return { ...actual, formatDate: vi.fn().mockReturnValue('2024-01-01'), // everything else stays real } })
vi.mocked() — Type-Safe Access to Mock
import { vi, expect } from 'vitest' import { fetchUser } from './api' vi.mock('./api') it('is typed', async () => { vi.mocked(fetchUser).mockResolvedValue({ id: 2, name: 'Bob' }) const user = await fetchUser(2) expect(user.name).toBe('Bob') })
Auto-Mocking
vi.mock('./heavyModule') // all exports become vi.fn()
Vitest auto-generates mocks for every export. Functions become vi.fn(), classes have mocked constructors and methods.
vi.doMock / vi.doUnmock (Dynamic, Not Hoisted)
it('dynamic mock', async () => { vi.doMock('./config', () => ({ apiUrl: 'http://test' })) const { apiUrl } = await import('./config') expect(apiUrl).toBe('http://test') vi.doUnmock('./config') })
Use vi.doMock when you need conditional or test-scoped mocking (it is NOT hoisted).
Mocking Default Exports
vi.mock('./logger', () => ({ default: vi.fn(), })) import logger from './logger' logger('msg') expect(logger).toHaveBeenCalledWith('msg')
Mocking Classes
vi.mock('./Database', () => { return { Database: vi.fn().mockImplementation(() => ({ connect: vi.fn().mockResolvedValue(true), query: vi.fn().mockResolvedValue([]), close: vi.fn(), })), } }) import { Database } from './Database' const db = new Database() await db.connect() expect(db.connect).toHaveBeenCalled()
Mocking Timers
import { vi, it, expect } from 'vitest' it('advances timers', () => { vi.useFakeTimers() const fn = vi.fn() setTimeout(fn, 1000) expect(fn).not.toHaveBeenCalled() vi.advanceTimersByTime(1000) expect(fn).toHaveBeenCalledTimes(1) vi.useRealTimers() })
| Timer Method | Effect |
|---|---|
vi.useFakeTimers() | Replace global timers with fakes |
vi.useRealTimers() | Restore real timers |
vi.advanceTimersByTime(ms) | Advance clock by ms |
vi.advanceTimersByTimeAsync(ms) | Async version (runs microtasks) |
vi.runAllTimers() | Run all pending timers |
vi.runAllTimersAsync() | Async version |
vi.runAllTicks() | Run all microtasks (process.nextTick) |
vi.clearAllTimers() | Clear all pending timers |
vi.setSystemTime(date) | Set Date.now() to a specific time |
vi.getRealSystemTime() | Get the real wall-clock time |
Mocking Date
vi.useFakeTimers() vi.setSystemTime(new Date('2024-01-15')) expect(new Date().toISOString()).toMatch('2024-01-15') vi.useRealTimers()
Mocking Environment Variables
it('reads env var', () => { vi.stubEnv('API_URL', 'http://localhost:3000') expect(process.env.API_URL).toBe('http://localhost:3000') vi.unstubAllEnvs() })
Mocking Globals
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ json: () => Promise.resolve({ data: 42 }), ok: true, })) // restore vi.unstubAllGlobals()
Clearing, Resetting, Restoring Mocks
| Method | Effect |
|---|---|
mockFn.mockClear() | Clear call history (.mock.calls, .mock.results) |
mockFn.mockReset() | Clear + remove all implementations |
mockFn.mockRestore() | Clear + restore original implementation (spies only) |
vi.clearAllMocks() | mockClear on all mocks |
vi.resetAllMocks() | mockReset on all mocks |
vi.restoreAllMocks() | mockRestore on all mocks |
In config, auto-apply between tests:
export default defineConfig({ test: { clearMocks: true, // clear after each test mockReset: false, // (Jest's name is resetMocks; Vitest's is mockReset) restoreMocks: false, }, })
Inspecting Mock Calls
const fn = vi.fn() fn(1, 2) fn(3, 4) fn.mock.calls // [[1, 2], [3, 4]] fn.mock.calls[0] // [1, 2] fn.mock.results // [{ type: 'return', value: undefined }, ...] fn.mock.instances // `this` for each call fn.mock.lastCall // [3, 4]