ACTIVATE when writing Vitest tests, creating test files, using vi.fn()/vi.mock()/vi.spyOn(), or test factories. ACTIVATE for 'Vitest', 'test convention', 'it.each', 'test double', 'DAMP test', 'spy vs mock'. Covers: DAMP over DRY, AAA pattern, vi.fn()/vi.spyOn()/vi.mock() patterns, spy over mock, what NOT to test, it.each() format selection (template vs object), factory functions, exception testing, NestJS integration test setup, structured assertions. DO NOT use for: TDD workflow/iterations (see vitest-tdd-workflow), PHP/PHPUnit tests (see php-test-conventions).
From vitestnpx claudepluginhub fabiensalles/claude-marketplace --plugin vitestThis skill uses the workspace's default tool permissions.
references/test-examples.mdDispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Executes pre-written implementation plans: critically reviews, follows bite-sized steps exactly, runs verifications, tracks progress with checkpoints, uses git worktrees, stops on blockers.
Guides idea refinement into designs: explores context, asks questions one-by-one, proposes approaches, presents sections for approval, writes/review specs before coding.
See also:
vitest-tdd-workflowfor TDD workflow and iteration patterns.
| Test Type | Setup | Purpose |
|---|---|---|
| Unit | No DI container, pure logic | Domain models, services |
| Integration | NestJS Test.createTestingModule() | Services with real dependencies |
| E2E | supertest + full app | HTTP request/response, full flow |
Prefer DAMP (Descriptive And Meaningful Phrases) over DRY in tests.
Avoid beforeEach(). Keep the full test lifecycle in each test case:
it('should mark tenant as eligible when lease is active', () => {
const lease = createActiveLease();
const specification = new IsTenantEligible();
const result = specification.isSatisfiedBy(lease);
expect(result).toBe(true);
});
Respect Arrange-Act-Assert or Given-When-Then structure with blank line separators.
Verify AFTER the act, not before (AAA compliance):
vi.fn() -- Simple stubs for dependenciesvi.spyOn() -- Spy on real objectsvi.mock() -- Module-level mocking| Worth testing | Not worth testing |
|---|---|
| Business logic / domain rules | Simple DTOs with only properties |
| Validation logic | Events with only properties |
| Calculations / transformations | Data containers |
| State machines / workflows | Entities with only getters/setters |
${})When writing test doubles, parameterized tests, or factory functions, read
references/test-examples.mdfor complete vi.fn/spyOn/mock patterns, it.each examples, and factory patterns.
When writing exception tests or NestJS integration tests, read
references/test-examples.mdfor toThrow patterns and Test.createTestingModule setup.
| Situation | Approach |
|---|---|
| Simple value objects | Direct instantiation |
| Complex dependencies | vi.fn() stubs |
| Spy on real method | vi.spyOn() |
| Module replacement | vi.mock() |
| Same logic, different data | it.each() (object or template literal) |
| Duplicated factory | Shared factory file |
| Verify method called | Spy after act |
| Setup code | In test body (DAMP) |
| Compare objects | toEqual + expect.objectContaining |
| Test Type | File pattern | Base setup |
|---|---|---|
| Unit | *.spec.ts | None |
| Integration | *.integration-spec.ts | Test.createTestingModule() |
| E2E | *.e2e-spec.ts | supertest + app |