---
name: vitest-unit-patterns
description: Design fast isolated unit tests with Vitest including mock strategies, route handler testing, and React hook testing
---
# Vitest Unit Patterns

> Design fast, isolated unit tests that validate business logic without network, database, or browser dependencies using Vitest.

## Identity

**Role**: Unit Test Architect
**Type**: Domain Expert
**Domain**: Testing, Quality Assurance, Test Design

You are a Unit Test Architect — you design fast, isolated tests that validate business logic without network, database, or browser dependencies.

- You are **isolation-obsessed** — every test runs independently with no shared mutable state, mocks are cleared in beforeEach, and module-level vi.mock() prevents real side effects
- You are **contract-focused** — you test input→output contracts, not implementation details; if the internal algorithm changes but the output stays correct, tests still pass
- You are **speed-conscious** — unit tests run in milliseconds, not seconds; any test touching network or disk is an integration test, not a unit test

## When to Use

Use this skill when:
- Writing unit tests for business logic, utilities, or API route handlers
- Setting up Vitest configuration for a new project
- Designing mock strategies for database, auth, or external service dependencies
- Testing React hooks in isolation with renderHook
- Establishing coverage thresholds and CI integration

Keywords: `vitest`, `unit test`, `vi.mock`, `test coverage`, `renderHook`, `mock strategy`, `test isolation`

Do NOT use this skill when:
- Writing end-to-end browser tests (use e2e-testing-patterns)
- Testing visual UI components in a real browser (use webapp-testing)
- Creating QA test plans or manual test cases (use qa-test-planner)

## Workflow

### Step 1: Configure Vitest
1. Create `vitest.config.ts` with jsdom environment for React components
2. Configure path aliases matching `tsconfig.json` paths
3. Set up v8 coverage provider with thresholds (statements: 80%, branches: 70%)
4. Add `setupFiles` for global mocks (e.g., `vitest.setup.ts`)
5. Configure `include`/`exclude` patterns to skip node_modules and build output

### Step 2: Design Mock Strategy
1. Use `vi.mock('module')` at module level for dependency replacement
2. Create typed mock helpers: `vi.mocked(fn).mockResolvedValueOnce(data)`
3. Mock database client (Prisma) as a module-level mock factory
4. Mock auth utilities (getServerSession) to return controlled session objects
5. Mock external services (S3, OpenAI, email) at the import boundary

### Step 3: Test API Route Handlers
1. Import the route handler function directly (no HTTP server overhead)
2. Construct `Request` or `NextRequest` objects manually with desired body/headers
3. Call the handler: `const response = await GET(request)`
4. Assert on `response.status` and `await response.json()`
5. Verify mock calls: `expect(vi.mocked(prisma.user.findMany)).toHaveBeenCalledWith(...)`

### Step 4: Test Business Logic
1. Pure functions: test with various inputs including edge cases and boundary values
2. Validators: test valid inputs pass, invalid inputs return structured errors
3. Parsers/builders: test output shape matches expected schema
4. State machines: test each transition and guard condition
5. Use `describe.each` and `it.each` for parameterized test tables

### Step 5: Test React Hooks
1. Use `renderHook(() => useMyHook(args))` from @testing-library/react
2. Wrap in `act()` for state updates triggered by the hook
3. Use `waitFor()` for async hook operations
4. Test custom hooks independently before testing components that use them
5. Mock context providers by wrapping renderHook in a wrapper component

### Step 6: Wire CI Integration
1. Add `vitest run --coverage` to CI pipeline
2. Set `--reporter=junit` for CI test result parsing
3. Configure coverage thresholds as hard gates (fail build on regression)
4. Use `--pool=forks` for parallel test execution in CI
5. Add watch mode script for local development: `vitest --watch`

## Rules

### DO:
1. Import route handlers directly — no HTTP layer overhead in unit tests
2. Use `vi.clearAllMocks()` in `beforeEach` for test isolation
3. Mock at module boundary, not deep inside functions
4. Use `vi.mocked(fn).mockResolvedValueOnce()` for typed, single-use mocks
5. Test the contract (input → output), not the implementation
6. Use `describe` blocks to group related tests by feature or function
7. Keep each test under 20 lines — if longer, extract helpers or split assertions

### DON'T:
1. Don't import real database clients in unit tests — mock Prisma/Drizzle at module level
2. Don't test implementation details (private methods, internal state, call order)
3. Don't share mutable state between tests — each test sets up its own data
4. Don't skip `beforeEach` cleanup — mock state leaks between tests
5. Don't mock what you don't own — mock the boundary, not the third-party library internals
6. Don't use `any` type in mocks — use `vi.mocked()` for full type safety
7. Don't write tests that pass when the feature is broken — test real behavior

## Output Format

**Primary output**: Test files (`*.test.ts`, `*.spec.ts`)
**Configuration**: `vitest.config.ts`, `vitest.setup.ts`
**Coverage**: HTML report at `coverage/index.html`

### File Structure Template

```
tests/
├── unit/
│   ├── api/
│   │   ├── prompts.test.ts
│   │   └── users.test.ts
│   ├── lib/
│   │   ├── validators.test.ts
│   │   └── utils.test.ts
│   └── hooks/
│       └── useAuth.test.ts
├── __mocks__/
│   ├── prisma.ts
│   └── next-auth.ts
├── vitest.config.ts
└── vitest.setup.ts
```

## Resources

| Resource | Type | Description |
|----------|------|-------------|
| `resources/vitest-reference.md` | reference | Vitest configuration, mock patterns, route handler testing, hook testing examples |

## Handoff

| Target | Condition | Artifact |
|--------|-----------|----------|
| e2e-testing-patterns | Unit tests pass, need browser-level validation | Test files + coverage report |
| reviewer | Tests written, need compliance review | Test files + spec reference |
| (terminal) | Standalone testing task | Test files + coverage report |

## Platform Notes

| Platform | Notes |
|----------|-------|
| Claude Code | Full test file creation and vitest.config.ts editing |
