Agent skill
testing-anti-patterns
Use when writing or changing tests, adding mocks, or tempted to add test-only methods to production code - prevents testing mock behavior and production pollution
Install this agent skill to your Project
npx add-skill https://github.com/timequity/plugins/tree/main/craft-coder/testing-anti-patterns
SKILL.md
Testing Anti-Patterns
Overview
Tests must verify real behavior, not mock behavior. Mocks are a means to isolate, not the thing being tested.
Core principle: Test what the code does, not what the mocks do.
The Iron Laws
1. NEVER test mock behavior
2. NEVER add test-only methods to production classes
3. NEVER mock without understanding dependencies
Anti-Pattern 1: Testing Mock Behavior
The violation:
// ❌ BAD: Testing that the mock exists
test('renders sidebar', () => {
render(<Page />);
expect(screen.getByTestId('sidebar-mock')).toBeInTheDocument();
});
Why wrong: You're verifying the mock works, not that the component works.
The fix:
// ✅ GOOD: Test real component
test('renders sidebar', () => {
render(<Page />); // Don't mock sidebar
expect(screen.getByRole('navigation')).toBeInTheDocument();
});
Gate Function
BEFORE asserting on any mock element:
Ask: "Am I testing real behavior or just mock existence?"
IF mock existence: STOP - Delete assertion or unmock
Anti-Pattern 2: Test-Only Methods in Production
The violation:
// ❌ BAD: destroy() only used in tests
class Session {
async destroy() { // Looks like production API!
await this._workspaceManager?.destroyWorkspace(this.id);
}
}
Why wrong: Production class polluted with test-only code.
The fix:
// ✅ GOOD: Test utilities handle cleanup
// In test-utils/
export async function cleanupSession(session: Session) {
const workspace = session.getWorkspaceInfo();
if (workspace) {
await workspaceManager.destroyWorkspace(workspace.id);
}
}
Anti-Pattern 3: Mocking Without Understanding
The violation:
// ❌ BAD: Mock breaks test logic
test('detects duplicate', () => {
vi.mock('ConfigWriter'); // Prevents config write test depends on!
await addServer(config);
await addServer(config); // Should throw - but won't!
});
Why wrong: Mocked method had side effect test depended on.
The fix:
// ✅ GOOD: Mock at correct level
test('detects duplicate', () => {
vi.mock('SlowNetworkCall'); // Mock only the slow part
await addServer(config); // Config written
await addServer(config); // Duplicate detected ✓
});
Gate Function
BEFORE mocking any method:
1. What side effects does the real method have?
2. Does this test depend on any of those side effects?
3. Do I fully understand what this test needs?
IF unsure: Run test with real implementation FIRST
Anti-Pattern 4: Incomplete Mocks
The violation:
// ❌ BAD: Partial mock
const mockResponse = {
status: 'success',
data: { userId: '123' }
// Missing: metadata that downstream code uses
};
The fix:
// ✅ GOOD: Mirror real API completely
const mockResponse = {
status: 'success',
data: { userId: '123', name: 'Alice' },
metadata: { requestId: 'req-789', timestamp: 1234567890 }
};
Quick Reference
| Anti-Pattern | Fix |
|---|---|
| Assert on mock elements | Test real component or unmock |
| Test-only methods in production | Move to test utilities |
| Mock without understanding | Understand dependencies first |
| Incomplete mocks | Mirror real API completely |
| Tests as afterthought | TDD - tests first |
Red Flags
- Assertion checks for
*-mocktest IDs - Methods only called in test files
- Mock setup is >50% of test
- Test fails when you remove mock
- Mocking "just to be safe"
Integration
Complementary skills:
- test-driven-development - TDD prevents these anti-patterns
- testing - General testing best practices
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
claude-code-course
Learn Claude Code in 5 hands-on lessons. From basics to building applications. Use when: user wants to learn Claude Code, asks "how do I...", or is new. Triggers: "learn", "teach me", "how does this work", "I'm new", "course".
foundations
Claude Code basics for new users. Covers essential concepts and commands. Use when: user is new to Claude Code or routed here by learning-path assessment.
advanced
Claude Code mastery for power users. Build agents, MCP servers, publish plugins. Use when: user wants to create agents, build integrations, or publish plugins.
lessons
Lesson content for Claude Code Course. Use when: loading lesson content. Internal skill - contains lesson files.
intermediate
Claude Code customization for comfortable users. Covers skills, commands, MCP, hooks. Use when: user knows basics and wants to customize Claude Code.
course-help
Help and navigation for Claude Code Course. Use when: user asks about the course, lessons, or progress. Triggers: "help", "course help", "what lessons", "my progress".
Didn't find tool you were looking for?