Vue · Testing

Vue 3 Testing with Vitest

Vitest is the natural test runner for a Vite-based Vue project — fast, Jest-compatible, and sharing your Vite config. The harder skill is testing behaviour instead of implementation.

John Kihiu12 min read

Vitest has become the default test runner for Vue 3 projects because it is built on Vite: it reuses your existing Vite config, starts fast, and offers a Jest-compatible API so most testing knowledge transfers directly. The tooling is the easy part. The skill that actually determines whether your tests help or hinder is testing behaviour rather than implementation details.

Why Vitest fits

Because Vitest shares your Vite pipeline, there is no separate build configuration to maintain and no mismatch between how your code runs in development and how it runs in tests. It is fast, supports watch mode with the same instant feedback Vite gives you, and its API mirrors Jest, so describe, it, and expect work as you would expect. For a Vite-based Vue project, it is the path of least resistance and the right default.

Test composables directly

Composables are just functions returning reactive state, which makes them the easiest and highest-value thing to test — you call the composable and assert on what it returns, no component required. Because so much of your logic lives in composables when you use the Composition API well, testing them directly covers a lot of ground cheaply:

TypeScript · testing a composable
import { useCounter } from './useCounter'

it('increments', () => {
  const { count, increment } = useCounter()
  expect(count.value).toBe(0)
  increment()
  expect(count.value).toBe(1)
})

Component testing

For components, use Vue Testing Library (or Vue Test Utils) to render a component and interact with it as a user would — find elements by their text or role, click, type, and assert on what the user sees. Testing Library's philosophy pushes you toward testing behaviour: you assert that the right thing appears after an interaction, not that an internal method was called or a specific data property changed.

Test behaviour, not implementation

The most common testing mistake is asserting on internal details — that a method ran, that a private ref holds a value. Those tests break every time you refactor, even when behaviour is unchanged, so they punish improvement. Test what the user experiences instead: given this input and interaction, the right output appears. Those tests survive refactoring and actually protect against regressions.

Vitest is the natural choice for Vue 3 testing — fast, Jest-compatible, and sharing your Vite config — with composables as the cheap high-value target and Testing Library for user-centric component tests. Lean into testing behaviour over implementation, and your suite catches real regressions while staying resilient to refactoring, instead of breaking every time you improve the code it was meant to protect.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.