Testing Anti-Patterns
Never test mock behavior. Never add test-only methods to production classes. Understand dependencies before mocking. Language-agnostic principles with TypeScript/Jest and Python/pytest examples.
What this skill does
# 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. **Following strict TDD prevents these anti-patterns.** See the Test-Driven Development skill (available in the skill library) for the complete TDD workflow. ## When to Use This Skill Activate this skill when: - **Writing or changing tests** - Verify tests cover real behavior - **Adding mocks** - Ensure mocking is necessary and correct - **Reviewing test failures** - Check if mock behavior is the issue - **Tempted to add test-only methods** - STOP and reconsider - **Tests feel overly complex** - Sign of over-mocking ## The Iron Laws ``` 1. NEVER test mock behavior 2. NEVER add test-only methods to production classes 3. NEVER mock without understanding dependencies 4. NEVER create incomplete mocks 5. NEVER treat tests as afterthought ``` ## Core Anti-Pattern Categories ### 1. Testing Mock Behavior Asserting on mock elements instead of real behavior. **Fix:** Test real component or don't mock it. **→** [core-anti-patterns.md](references/core-anti-patterns.md#anti-pattern-1-testing-mock-behavior) ### 2. Test-Only Methods in Production Methods in production classes only used by tests. **Fix:** Move to test utilities. **→** [core-anti-patterns.md](references/core-anti-patterns.md#anti-pattern-2-test-only-methods-in-production) ### 3. Mocking Without Understanding Mocking without understanding dependencies/side effects. **Fix:** Understand first, mock minimally. **→** [core-anti-patterns.md](references/core-anti-patterns.md#anti-pattern-3-mocking-without-understanding) ### 4. Incomplete Mocks Partial mocks missing fields downstream code needs. **Fix:** Mirror complete API structure. **→** [completeness-anti-patterns.md](references/completeness-anti-patterns.md#anti-pattern-4-incomplete-mocks) ### 5. Tests as Afterthought Implementation "complete" without tests. **Fix:** TDD - write test first. **→** [completeness-anti-patterns.md](references/completeness-anti-patterns.md#anti-pattern-5-tests-as-afterthought) ## Quick Detection Checklist Run this checklist before committing any test: **Language-agnostic checks:** ``` □ Am I asserting on mock behavior instead of real behavior? → TypeScript: testId='*-mock', expect(mock).toHaveBeenCalled() → Python: mock.assert_called(), mock.call_count → If yes: STOP - Test real behavior or unmock □ Does this method only exist for tests? → TypeScript: destroy(), reset(), clear() only in *.test.ts → Python: _set_mock_*, _for_testing only in test_*.py → If yes: STOP - Move to test utilities □ Do I fully understand what I'm mocking? → If no: STOP - Run with real impl first, then mock minimally □ Is my mock missing fields the real API has? → TypeScript: Partial<T>, incomplete objects → Python: Mock() with few attributes, missing nested fields → If yes: STOP - Mirror complete API structure □ Did I write implementation before test? → If yes: STOP - Delete impl, write test first (TDD) □ Is mock setup >50% of test code? → If yes: Consider integration test with real components ``` **See:** [detection-guide.md](references/detection-guide.md) for comprehensive red flags and warning signs. ## The Bottom Line **Mocks are tools to isolate, not things to test.** Testing mock behavior indicates a problem. Fix: Test real behavior or question why mocking is necessary. **TDD prevents these patterns.** Write test first → Watch fail → Minimal implementation → Pass → Refactor. ## Navigation ### Detailed Anti-Pattern Analysis - **[Core Anti-Patterns](references/core-anti-patterns.md)** - Patterns 1-3: Mock behavior, test-only methods, uninformed mocking - **[Completeness Anti-Patterns](references/completeness-anti-patterns.md)** - Patterns 4-5: Incomplete mocks, tests as afterthought ### Detection & Prevention - **[Detection Guide](references/detection-guide.md)** - Red flags, warning signs, gate functions - **[TDD Connection](references/tdd-connection.md)** - How test-driven development prevents these patterns ### Language-Specific Examples - **[Python Examples](references/python-examples.md)** - Complete Python/pytest guide covering all 5 anti-patterns with unittest.mock and pytest-mock patterns, fixture best practices, and pytest-specific detection. Load when working with Python tests. ### Related Skills When using this skill, consider these complementary skills (if deployed in your skill bundle): - **test-driven-development**: Complete TDD workflow and red-green-refactor cycle - *Use case*: Implementing TDD discipline to prevent anti-patterns - *Integration*: TDD workflow prevents most anti-patterns by design - *Status*: Recommended - basic anti-patterns covered in this skill - **verification-before-completion**: Definition of "done" and verification protocols - *Use case*: Ensuring tests are part of completion criteria - *Integration*: Tests must pass before work is considered complete - *Status*: Recommended - testing mindset reinforcement *Note: All skills are independently deployable. This skill is fully functional without them.* ## Key Reminders 1. **Mocks isolate, don't prove** - Test real code, not mocks 2. **Production ignores tests** - No test-only methods 3. **Understand before mocking** - Know dependencies and side effects 4. **Complete mocks only** - Mirror full API structure 5. **Tests ARE implementation** - Not optional afterthought ## Red Flags - STOP **STOP immediately when:** - **Testing mock behavior** - TypeScript: Asserting on `*-mock` test IDs, `expect(mock).toHaveBeenCalled()` - Python: `mock.assert_called()`, `mock.call_count` without real behavior checks - **Adding test-only methods** - TypeScript: `destroy()`, `reset()` only in `*.test.ts` - Python: `_set_mock_*`, `_for_testing` with "For testing only" docstrings - **Mocking without understanding** - Adding `@patch` or `vi.mock()` "just to be safe" - Creating mocks from memory instead of API docs - **Incomplete mocks** - TypeScript: `Partial<T>`, missing nested objects - Python: `Mock()` for data objects, missing required fields - **Tests as afterthought** - Saying "tests can wait" or "ready for testing" - Implementation commits before test commits **When mocks become too complex:** Consider integration tests with real components. Often simpler and more valuable. ## Integration with Other Skills **Prerequisite:** Test-Driven Development skill - TDD prevents anti-patterns (recommended for complete workflow) **Complementary:** Verification-Before-Completion skill - Tests = done (ensures proper testing discipline) **Domain-specific:** webapp-testing, backend-testing for framework patterns (see skill library if available)
Related in Code Review
gstack
IncludedFast headless browser for QA testing and site dogfooding. Navigate pages, interact with elements, verify state, diff before/after, take annotated screenshots, test responsive layouts, forms, uploads, dialogs, and capture bug evidence. Use when asked to open or test a site, verify a deployment, dogfood a user flow, or file a bug with screenshots. (gstack)
startup-due-diligence
IncludedLegal due diligence review for seed-stage and Series A startups (US, Delaware C-Corp focus). Supports both investor and founder perspectives. Capabilities include: (1) Interactive document review and issue spotting; (2) Document request list generation; (3) Cap table and SAFE/convertible note analysis; (4) Red flag identification with severity ratings; (5) Diligence report generation. TRIGGERS: due diligence, DD, startup investment, cap table review, Series A, seed round, investor diligence, legal review startup, SAFE analysis, convertible note, 409A, founder vesting.
interview-master
IncludedThis skill should be used when the user asks to "generate interview questions", "prepare for interview", "optimize resume", "conduct mock interview", "analyze git commits for resume", "generate resume from code", "review my resume", or mentions interview preparation, career assistance, or extracting project experience from git history. Provides comprehensive interview and career development guidance for both job seekers and interviewers.
fix-issue
IncludedFixes GitHub issues using parallel analysis agents for root cause investigation, code exploration, and regression detection. Reads issue context from gh CLI, searches codebase and memory for related patterns, generates a fix with tests, and links the resolution back to the issue via PR. Includes prevention analysis to avoid recurrence. Use when debugging errors, resolving regressions, fixing bugs, or triaging issues.
sf-apex
IncludedGenerates and reviews Salesforce Apex code with 150-point scoring. TRIGGER when: user writes, reviews, or fixes Apex classes, triggers, test classes, batch/queueable/schedulable jobs, or touches .cls/.trigger files. DO NOT TRIGGER when: LWC JavaScript (use sf-lwc), Flow XML (use sf-flow), SOQL-only queries (use sf-soql), or non-Salesforce code.
swift-development
IncludedComprehensive Swift development for building, testing, and deploying iOS/macOS applications. Use when Claude needs to: (1) Build Swift packages or Xcode projects from command line, (2) Run tests with XCTest or Swift Testing framework, (3) Manage iOS simulators with simctl, (4) Handle code signing, provisioning profiles, and app distribution, (5) Format or lint Swift code with SwiftFormat/SwiftLint, (6) Work with Swift Package Manager (SPM), (7) Implement Swift 6 concurrency patterns (async/await, actors, Sendable), (8) Create SwiftUI views with MVVM architecture, (9) Set up Core Data or SwiftData persistence, or any other Swift/iOS/macOS development tasks.