Vitest Cheatsheet
Assertions (expect)
Use this Vitest reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
expect() Basics
import { expect } from 'vitest' expect(value) // creates an assertion chain expect(value).not.toBe(x) // negate any matcher
Equality Matchers
| Matcher | Checks |
|---|---|
.toBe(val) | Object.is() strict equality (primitives, same reference) |
.toEqual(val) | Deep equality (objects, arrays — recursively) |
.toStrictEqual(val) | Deep equality + checks undefined properties + class instances |
.toBeUndefined() | === undefined |
.toBeDefined() | !== undefined |
.toBeNull() | === null |
.toBeNaN() | isNaN() |
.toBeTruthy() | truthy |
.toBeFalsy() | falsy |
expect({ a: 1 }).toEqual({ a: 1 }) // passes expect({ a: 1 }).toStrictEqual({ a: 1 }) // passes expect(new Dog()).toStrictEqual({ name: 'Rex' }) // FAILS — different class
Number Matchers
| Matcher | Checks |
|---|---|
.toBeGreaterThan(n) | > n |
.toBeGreaterThanOrEqual(n) | >= n |
.toBeLessThan(n) | < n |
.toBeLessThanOrEqual(n) | <= n |
.toBeCloseTo(n, digits?) | Floating-point approximation (default 2 decimal digits) |
.toBeFinite() | Not Infinity or NaN |
.toBePositive() | > 0 |
.toBeNegative() | < 0 |
.toBeInteger() | No decimal part |
expect(0.1 + 0.2).toBeCloseTo(0.3, 5) expect(Math.PI).toBeCloseTo(3.14159, 5)
String Matchers
| Matcher | Checks |
|---|---|
.toContain(str) | Substring present |
.toMatch(str|regex) | Regex or substring match |
.toHaveLength(n) | .length === n |
expect('hello world').toContain('world') expect('foo123').toMatch(/\d+/) expect('foobar').toMatch(/^foo/)
.toStartWith/.toEndWithare not built-in — they come from thejest-extendedpackage viaexpect.extend.
Array and Iterable Matchers
| Matcher | Checks |
|---|---|
.toContain(item) | Array contains item (strict equality) |
.toContainEqual(item) | Array contains item (deep equality) |
.toHaveLength(n) | .length === n |
.toEqual(expect.arrayContaining([...])) | Array has at least these items |
expect([1, 2, 3]).toContain(2) expect([{ id: 1 }]).toContainEqual({ id: 1 }) expect([1, 2, 3]).toEqual(expect.arrayContaining([1, 3]))
Object Matchers
| Matcher | Checks |
|---|---|
.toMatchObject(obj) | Object contains at least the given subset |
.toHaveProperty(keyPath, val?) | Property exists (optional value check) |
expect({ a: 1, b: 2 }).toMatchObject({ a: 1 }) expect({ user: { id: 1 } }).toHaveProperty('user.id', 1) expect({ arr: [1, 2] }).toHaveProperty('arr[0]', 1)
Error / Exception Matchers
| Matcher | Checks |
|---|---|
.toThrow() | Function throws anything |
.toThrow(str) | Thrown message contains string |
.toThrow(regex) | Thrown message matches regex |
.toThrow(ErrorClass) | Thrown instance of class |
.toThrowError(...) | Alias for .toThrow |
.rejects.toThrow(...) | Async function rejects |
expect(() => { throw new Error('oops') }).toThrow('oops') expect(() => fn()).toThrow(TypeError) await expect(asyncFn()).rejects.toThrow('network error') await expect(asyncFn()).rejects.toBeInstanceOf(Error)
Wrap the call in an arrow function:
expect(() => fn())notexpect(fn()).
Promise Matchers
await expect(Promise.resolve(42)).resolves.toBe(42) await expect(Promise.reject(new Error('x'))).rejects.toThrow('x')
Function / Spy Matchers
| Matcher | Checks |
|---|---|
.toHaveBeenCalled() | Called at least once |
.toHaveBeenCalledTimes(n) | Called exactly n times |
.toHaveBeenCalledWith(...args) | Last call had these args |
.toHaveBeenLastCalledWith(...args) | Alias for above |
.toHaveBeenNthCalledWith(n, ...args) | nth call had these args |
.toHaveReturnedWith(val) | Returned this value |
.toHaveReturnedTimes(n) | Returned (not thrown) n times |
.toHaveLastReturnedWith(val) | Last return value |
const fn = vi.fn().mockReturnValue(42) fn('a', 'b') expect(fn).toHaveBeenCalledWith('a', 'b') expect(fn).toHaveBeenCalledTimes(1) expect(fn).toHaveReturnedWith(42)
Asymmetric Matchers (expect.*)
| Asymmetric Matcher | Meaning |
|---|---|
expect.any(Constructor) | Any instance of type |
expect.anything() | Anything except null/undefined |
expect.arrayContaining([...]) | Superset of given array |
expect.objectContaining({...}) | Superset of given object |
expect.stringContaining(str) | String containing substring |
expect.stringMatching(regex) | String matching regex |
expect.not.arrayContaining([...]) | Negated version |
expect({ id: expect.any(Number), name: 'Alice' }).toMatchObject({ id: expect.any(Number), name: expect.stringContaining('Ali'), }) expect(fn).toHaveBeenCalledWith( expect.objectContaining({ userId: expect.any(String) }) )
Custom Matchers
import { expect } from 'vitest' expect.extend({ toBeWithinRange(received: number, min: number, max: number) { const pass = received >= min && received <= max return { pass, message: () => `expected ${received} to${pass ? ' not' : ''} be within [${min}, ${max}]`, } }, }) // Usage: expect(50).toBeWithinRange(1, 100)
Add TypeScript types by augmenting interface Assertion in a .d.ts file.
expect.assertions / expect.hasAssertions
it('must run the callback assertion', async () => { expect.assertions(1) // exactly 1 assertion must run await new Promise<void>((resolve) => { asyncFn((result) => { expect(result).toBe('ok') resolve() }) }) }) it('at least one assertion runs', async () => { expect.hasAssertions() await expect(asyncFn()).resolves.toBeDefined() })
Soft Assertions
it('reports all failures', () => { expect.soft(1).toBe(2) // fails but continues expect.soft(3).toBe(3) // passes expect.soft('a').toBe('b') // fails but continues // all soft failures thrown at end of test })