Skip to content

Commit cb89973

Browse files
feat: 30 - test mocking patterns (#32)
* Initial version. * feat: add test-mocking-patterns skill with comprehensive guidance and examples * feat: enhance description for test-mocking-patterns skill with detailed guidance * feat: update description for test-mocking-patterns skill and remove license and compatibility sections
1 parent 3ffb660 commit cb89973

10 files changed

Lines changed: 866 additions & 2 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ its purpose, trigger phrases, and full instructions.
7878
| Skill | Description |
7979
|------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
8080
| **[pr-review](./skills/pr-review/)** | Pull request code review — reviews diffs for risk, security issues, API contract changes, dependency bumps, CI/CD and infrastructure changes. Produces concise Blocker / Important / Nit comments. |
81-
| **[test-data-management](./skills/test-data-management/)** | Test data setup and management — factory functions, parametrised tests, deterministic seeds, fixture reuse, and production-data rules for unit and integration tests. |
8281
| **[tdd-workflow](./skills/tdd-workflow/)** | Test-driven development: upfront SPEC.md planning + confirmation gate (avoids batch design), then vertical-sliced implementation (one test → one code cycle at a time, not all tests then all code). |
82+
| **[test-data-management](./skills/test-data-management/)** | Test data setup and management — factory functions, parametrised tests, deterministic seeds, fixture reuse, and production-data rules for unit and integration tests. |
83+
| **[test-mocking-patterns](./skills/test-mocking-patterns/)** | Test double selection and implementation — classifies mock, stub, spy, fake, and dummy; guides patching strategy and cleanup for Python (pytest-mock), JavaScript/TypeScript (Jest), and Scala (mockito-scala). |
8384
| **[test-unit-standards](./skills/test-unit-standards/)** | Reference for unit test standards across isolation, scope, naming, assertions, coverage, and fixtures. Language-specific guidance (pytest, Jest, MUnit) with principles and conventions. |
8485
| **[test-unit-write](./skills/test-unit-write/)** | Generate unit tests from scratch following language-specific standards. Analyzes source, selects mock strategies, and produces tests covering happy paths, failure conditions, and edge cases. |
8586
| **[test-unit-review](./skills/test-unit-review/)** | Systematically audit unit test suites. Runs test runner, checks isolation/scope/naming/assertions/coverage standards, and reports findings by severity (Blocker / Important / Nit). |

docs/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Navigation hub for all guides in this repository. Browse by category below.
88
|----|----|
99
| [Getting Started](./getting-started.md) | What skills are, how to install them, Copilot CLI usage |
1010
| [Contributing](../CONTRIBUTING.md) | Skill folder layout, frontmatter, description writing, body guidelines, PR process |
11+
| [Responsible Agent Use](./responsible-agent-use.md) | Not burning your Copilot token budget — context, models, agent mode, MCP, plugins, skills, and a must-do checklist |
1112
| [Skill Testing](./skill-testing.md) | Eval creation, fixtures, regression loops, trigger and description optimization |
1213
| [Troubleshooting](./troubleshooting.md) | Setup fixes for install, activation, and proxy issues |
1314

@@ -27,10 +28,10 @@ Navigation hub for all guides in this repository. Browse by category below.
2728
| [PR Review](./pr-review.md) | How the PR review skill works, what sections it applies, and how to trigger it |
2829
| [TDD Workflow](./tdd-workflow.md) | Test-driven development with: specification, confirmation gates, and vertical-sliced implementation |
2930
| [Test Data Management](./test-data-management.md) | How the test-data-management skill works, what it covers, and when it fires |
31+
| [Test Mocking Patterns](./test-mocking-patterns.md) | Double selection, patching strategies, cleanup, and language-specific guidance |
3032
| [Unit Test Standards](./test-unit-standards.md) | Reference for unit test standards across isolation, scope, naming, assertions, coverage, fixtures |
3133
| [Unit Test Writer](./test-unit-write.md) | Generate complete unit tests from scratch following language-specific standards |
3234
| [Unit Test Reviewer](./test-unit-review.md) | Systematically audit unit tests and report findings by severity |
33-
| [Responsible Agent Use](./responsible-agent-use.md) | Not burning your Copilot token budget — context, models, agent mode, MCP, plugins, skills, and a must-do checklist |
3435
| [Token Saving](./token-saving.md) | Keeping AI responses concise — how the token-saving skill works and when it applies |
3536

3637
> **Keep this index up to date.** When you add a new guide, add a row to the appropriate table above.

docs/test-mocking-patterns.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Test Mocking Patterns Skill
2+
3+
The `test-mocking-patterns` skill guides test double selection and implementation. It activates when you need to decide which double to use (mock, stub, spy, fake, dummy), implement a double in Python, JavaScript/TypeScript, or Scala, or diagnose a mock that isn't working.
4+
5+
---
6+
7+
## What it does
8+
9+
Given a dependency in the code under test, the skill:
10+
11+
1. **Classifies the dependency** — query (return value matters) vs command (side effect to verify) vs fire-and-forget
12+
2. **Recommends the right double** — stub, mock, spy, fake, or dummy based on intent
13+
3. **Provides implementation guidance** — correct patching paths, library calls, and cleanup
14+
4. **Diagnoses broken mocks** — wrong patch target, missing cleanup, over-specified assertions, wrong return type
15+
16+
---
17+
18+
## Double selection quick reference
19+
20+
| Dependency interaction | Recommended double |
21+
|---|---|
22+
| Returns a value the unit under test uses; no need to verify the call | **Stub** |
23+
| Called for a side effect; test must verify it was called | **Mock** |
24+
| Need to verify the call AND preserve the real return value | **Spy** |
25+
| Stateful in-process replacement of an interface | **Fake** |
26+
| Required by the type signature but never invoked | **Dummy** |
27+
28+
> Prefer stubs over mocks — stubs make fewer assumptions about internal behaviour, keeping tests less brittle.
29+
30+
---
31+
32+
## Languages covered
33+
34+
| Language | Libraries |
35+
|---|---|
36+
| Python | `pytest-mock`, `unittest.mock`, `responses`, `pytest-httpx`, `freezegun` |
37+
| JavaScript / TypeScript | Jest (`jest.fn()`, `jest.mock()`, `jest.spyOn()`) |
38+
| Scala | mockito-scala |
39+
40+
---
41+
42+
## How to trigger it
43+
44+
Ask naturally — the skill fires on intent:
45+
46+
```
47+
should I use a mock or stub for the HTTP client?
48+
what test double should I use for the payment gateway?
49+
my mock isn't being called — the real implementation runs instead
50+
where should I patch requests.get?
51+
how do I mock an environment variable?
52+
how do I verify a method was called with specific arguments?
53+
should I mock the boto3 client directly or wrap it?
54+
how do I freeze time in a pytest test?
55+
```
56+
57+
> **Does NOT trigger** for writing full test suites (use `test-unit-write`), reviewing test files for standards violations (use `test-unit-review`), or managing test data and fixtures (use `test-data-management`).
58+
59+
---
60+
61+
## Common patching mistakes
62+
63+
| Symptom | Likely cause | Fix |
64+
|---|---|---|
65+
| Mock is never called; real code runs | Mock not injected, or wrong patch target | Confirm the unit receives the mock; patch where the name is imported |
66+
| `assert_called` fails but real call visible in logs | Patching the source module, not the import location | Patch `mymodule.requests.get`, not `requests.get` |
67+
| Mock state bleeds between tests | No cleanup | Use `mocker` fixture (Python) or `jest.clearAllMocks()` in `beforeEach` |
68+
| Test breaks on unrelated internal changes | Over-specified assertions | Use `ANY` / `expect.any()` for irrelevant args |
69+
70+
---
71+
72+
## Key principles
73+
74+
### Patch where the name is imported (Python)
75+
76+
```python
77+
# Module under test: import requests as http_lib
78+
# ✅ — patch the name in the module under test
79+
mocker.patch("myapp.service.http_lib.get", return_value=stub_response)
80+
81+
# ❌ — patching the source has no effect on the already-imported alias
82+
mocker.patch("requests.get", return_value=stub_response)
83+
```
84+
85+
### Don't mock what you don't own
86+
87+
Avoid mocking third-party types (boto3, SQLAlchemy sessions, gRPC stubs) directly. Wrap them in a thin interface you control and mock that interface instead. The integration test verifying the real connector belongs in an integration test, not a unit test.
88+
89+
### Use freezegun for datetime (Python)
90+
91+
`datetime` is a C extension — patching it directly is fragile. Use `freezegun`:
92+
93+
```python
94+
from freezegun import freeze_time
95+
96+
@freeze_time("2025-01-15 12:00:00")
97+
def test_timestamp_is_fixed():
98+
...
99+
```
100+
101+
---
102+
103+
## Installation
104+
105+
The skill is installed with the rest of the toolkit:
106+
107+
```bash
108+
npx skills add https://github.com/AbsaOSS/agentic-toolkit -g
109+
```
110+
111+
To install only this skill:
112+
113+
```bash
114+
npx skills add https://github.com/AbsaOSS/agentic-toolkit -g --skill test-mocking-patterns
115+
```

0 commit comments

Comments
 (0)