# Testing Unit Vitest

> Writes and maintains unit tests using Vitest. To be used for testing business logic in services and utilities. Use when this capability is needed.

- Skill: `tomevault-io/testing-unit-vitest` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/testing-unit-vitest`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/testing-unit-vitest/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/testing-unit-vitest

---


# Unit Testing Skill

When asked to write or maintain unit tests, follow these guidelines:

## When to Write Unit Tests

- **New services/utilities**: Write tests when creating new business logic
- **Bug fixes**: Add tests to verify bug resolution and prevent regression
- **Complex logic**: Test edge cases, boundary conditions, and error handling
- **Refactoring**: Ensure tests pass before and after code changes

## File Naming and Location

- **Colocate tests**: Place test files next to source files (e.g., `validation.spec.ts` next to `validation.ts`)
- **Naming convention**: Use `{filename}.spec.ts` pattern
- **Separate E2E**: Keep Playwright tests in `tests/` directory for HTTP-layer integration tests

## Test Structure

Use describe/it blocks with arrange-act-assert pattern:

```typescript
import { describe, it, expect, beforeEach, vi } from 'vitest';

describe('MyService', () => {
  beforeEach(() => {
    // Setup for each test
  });

  describe('methodName', () => {
    it('should do something specific', () => {
      // Arrange: Set up test data
      const input = { /* ... */ };
      
      // Act: Execute the code under test
      const result = service.method(input);
      
      // Assert: Verify the outcome
      expect(result).toBe(expected);
    });
  });
});
```

## Mocking Dependencies

Use `vi.fn()` for repository interfaces and external services:

```typescript
import { vi } from 'vitest';

const mockRepo = {
  save: vi.fn(),
  findById: vi.fn(),
  findAll: vi.fn(),
};

// Inject mocked repository
const service = new MyService(mockRepo);

// Set return values
vi.mocked(mockRepo.findById).mockReturnValue(mockData);

// Verify calls
expect(mockRepo.save).toHaveBeenCalledWith(expected);
expect(mockRepo.save).toHaveBeenCalledTimes(1);
```

## Running Tests

- **Watch mode**: `npm run test:dev` - Auto-rerun tests during development
- **One-time**: `npm run test:unit` - Run all unit tests once
- **Coverage**: `npm run test:coverage` - Generate coverage report
- **E2E**: `npm test` - Run Playwright tests independently

## Coverage Expectations

- **Services/utilities**: Aim for >80% coverage
- **Edge cases**: Test boundary conditions (0, 1, max, max+1)
- **Error paths**: Verify error handling and validation
- **Business rules**: Test all conditional logic and state transitions

## Best Practices

- **Test behavior, not implementation**: Focus on inputs/outputs, not internal details
- **One assertion per test**: Keep tests focused (exceptions for related checks)
- **Clear test names**: Use descriptive `it('should...')` statements
- **Isolated tests**: Each test should run independently
- **Fast execution**: Mock I/O operations to keep tests fast

## Common Vitest Matchers

```typescript
expect(value).toBe(expected);              // Strict equality
expect(value).toEqual(expected);           // Deep equality
expect(value).toBeInstanceOf(Class);       // Instance check
expect(value).toBeUndefined();             // Undefined check
expect(array).toHaveLength(3);             // Array length
expect(() => fn()).toThrow(ErrorClass);    // Exception check
expect(mockFn).toHaveBeenCalledWith(arg);  // Mock verification
expect(mockFn).toHaveBeenCalledTimes(1);   // Call count
```

## Reference

For advanced features, see [Vitest documentation](https://vitest.dev/):
- Snapshot testing
- Testing async code
- Custom matchers
- Performance testing

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/albertobasalo) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-16 -->

