Unit testing and TDD expert for Vitest/Jest. Red-green-refactor workflow, mocking strategies, coverage analysis, and ESM mocking patterns. Use for writing tests, implementing TDD, or setting up test coverage.
View on GitHubFebruary 4, 2026
Select agents to install to:
npx add-skill https://github.com/anton-abyzov/specweave/blob/main/plugins/specweave-testing/skills/unit-testing/SKILL.md -a claude-code --skill unit-testingInstallation paths:
.claude/skills/unit-testing/# Unit Testing & TDD Expert - Vitest/Jest
## Test-Driven Development (TDD)
### Red-Green-Refactor Cycle
```typescript
// 1. RED: Write failing test
describe('Calculator', () => {
it('should add two numbers', () => {
const calc = new Calculator();
expect(calc.add(2, 3)).toBe(5); // FAILS - doesn't exist
});
});
// 2. GREEN: Minimal implementation
class Calculator {
add(a: number, b: number): number {
return a + b;
}
}
// 3. REFACTOR: Improve design
class Calculator {
add(...numbers: number[]): number {
return numbers.reduce((sum, n) => sum + n, 0);
}
}
```
### TDD Checklist
- [ ] RED: Test fails for the RIGHT reason
- [ ] GREEN: Simplest code that passes
- [ ] REFACTOR: All tests still green
## Basic Test Structure
```typescript
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
describe('UserService', () => {
let service: UserService;
beforeEach(() => {
service = new UserService();
vi.clearAllMocks();
});
it('should create user', () => {
const user = service.create({ name: 'John', email: 'john@test.com' });
expect(user).toMatchObject({
id: expect.any(String),
name: 'John',
email: 'john@test.com'
});
});
it('should throw for invalid email', () => {
expect(() => service.create({ email: 'invalid' })).toThrow('Invalid email');
});
});
```
## Mocking Strategies
### 1. Mock Functions
```typescript
const mockFn = vi.fn();
mockFn.mockReturnValue(42);
expect(mockFn()).toBe(42);
expect(mockFn).toHaveBeenCalledTimes(1);
```
### 2. Mock Modules
```typescript
vi.mock('./database', () => ({
query: vi.fn().mockResolvedValue([{ id: 1 }])
}));
import { query } from './database';
```
### 3. ESM Mocking with vi.hoisted()
**CRITICAL for ESM modules**:
```typescript
// ✅ Define mocks in hoisted context FIRST
const { mockFn } = vi.hoisted(() => ({
mockFn: vi.fn()
}));
vi.mock('./module', () => ({
myFunc: mockFn
}));
import { myFunc } from './module';
`