Files
leo-claude-mktplace/plugins/saas-test-pilot/skills/mock-patterns.md
lmiranda 2d51df7a42 feat(marketplace): command consolidation + 8 new plugins (v8.1.0 → v9.0.0) [BREAKING]
Phase 1b: Rename all ~94 commands across 12 plugins to /<noun> <action>
sub-command pattern. Git-flow consolidated from 8→5 commands (commit
variants absorbed into --push/--merge/--sync flags). Dispatch files,
name: frontmatter, and cross-reference updates for all plugins.

Phase 2: Design documents for 8 new plugins in docs/designs/.

Phase 3: Scaffold 8 new plugins — saas-api-platform, saas-db-migrate,
saas-react-platform, saas-test-pilot, data-seed, ops-release-manager,
ops-deploy-pipeline, debug-mcp. Each with plugin.json, commands, agents,
skills, README, and claude-md-integration. Marketplace grows from 12→20.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 14:52:11 -05:00

2.6 KiB

description
description
Mocking, stubbing, and dependency injection strategies for tests

Mock Patterns Skill

Overview

Mocking strategies and best practices for isolating code under test from external dependencies.

When to Mock

Situation Mock? Reason
External API calls Yes Unreliable, slow, costs money
Database queries Depends Mock for unit, real for integration
File system Depends Mock for unit, tmpdir for integration
Time/date functions Yes Deterministic tests
Random/UUID generation Yes Reproducible tests
Pure utility functions No Fast, deterministic, no side effects
Internal business logic No Test the real thing

Python Mocking

unittest.mock / pytest-mock

patch("module.path.to.dependency")     # Replaces at import location
patch.object(MyClass, "method")        # Replaces on specific class
MagicMock(return_value=expected)       # Creates callable mock
MagicMock(side_effect=Exception("e"))  # Raises on call

Critical rule: Patch where the dependency is USED, not where it is DEFINED.

  • If views.py imports from services import send_email, patch views.send_email, NOT services.send_email.

pytest-mock (preferred)

Use the mocker fixture for cleaner syntax:

  • mocker.patch("module.function") — auto-cleanup after test
  • mocker.spy(obj, "method") — record calls without replacing

JavaScript Mocking

Jest

jest.mock("./module")              // Auto-mock entire module
jest.spyOn(object, "method")       // Spy without replacing
jest.fn().mockReturnValue(value)   // Create mock function

Vitest

vi.mock("./module")                // Same API as Jest
vi.spyOn(object, "method")
vi.fn().mockReturnValue(value)

Mock vs Stub vs Spy

Type Behavior Use When
Mock Replace entirely, return fake data Isolating from external service
Stub Provide canned responses Controlling specific return values
Spy Record calls, keep real behavior Verifying interactions without changing behavior

Dependency Injection Patterns

Prefer DI over mocking when possible:

  • Constructor injection: pass dependencies as constructor args
  • Function parameters: accept collaborators as arguments with defaults
  • Context managers: swap implementations via context

DI makes tests simpler and avoids brittle mock paths.

Anti-Patterns

  • Mocking too deep (mock chains: mock.return_value.method.return_value)
  • Asserting on mock call counts instead of outcomes
  • Mocking the system under test
  • Not resetting mocks between tests (use autouse fixtures or afterEach)