unit-testing
Unit Testing Skill
Framework-agnostic unit testing best practices. Apply these patterns regardless of language or test runner.
Core Principles
- Test behavior, not implementation — tests should survive internal refactoring
- One behavior per test — not one method per test
- AAA structure — Arrange / Act / Assert, always
- Prefer fakes and spies over mocks — less coupling to mocking frameworks
- Name tests as readable sentences — a non-developer should understand the scenario
Workflow
Writing New Tests
- Identify the unit of behavior (a business scenario, not a method)
- Name the test using
Subject_Scenario_ExpectedBehaviorpattern - Structure with AAA — keep each section minimal
- Use Object Mother or Builder for test data setup
- Assert on observable behavior only — never internal state via reflection
Reviewing Existing Tests
Check for these anti-patterns (see references/anti-patterns.md):
- Tests that verify
Times.Onceon mocks instead of outcomes - Test names with "Test", "Should", "Assert", "Verify"
- Multiple Act phases in one test
- Getters added only for testing
- Logic in test constructors / shared mutable state
Choosing Test Doubles
| Double | Use when |
|---|---|
| Fake | Replacing infrastructure (DB, email, queue) — working but simple impl |
| Stub | Controlling return values for the SUT |
| Spy | Verifying side effects (what was sent, stored, emitted) |
| Mock | Last resort — when Fake/Spy would be too complex |
| Dummy | Satisfying required params that are never used |
Default: Prefer Fake + Spy. Use Mock only when a handwritten double would be complex.
Test Naming
Pattern: Subject_Scenario_ExpectedBehavior
✅ Deactivating_AnActiveSubscription_Succeeds
✅ Creating_WithTooShortPassword_IsInvalid
✅ PlacingOrder_WithNoItems_Fails
❌ TestDeactivateSubscription
❌ ShouldThrowWhenPasswordTooShort
❌ DeactivateSubscription_SetsStatusToInactive
Rules:
- No technical terms (Test, Assert, Should, Verify)
- Present tense or readable active language
- Underscores over camelCase for readability
- Name the SUT variable
sut
Key Patterns
AAA Pattern
// Arrange — set up SUT and dependencies
// Act — single method call on sut
// Assert — verify outcome (return value, state, or interaction)
Never multiple Act-Assert cycles in one test — split them.
Object Mother
Static factory for pre-configured test objects. Eliminates setup duplication.
See references/patterns.md for full examples.
Builder Pattern
Fluent builder for complex test objects with many optional fields.
See references/patterns.md for full examples.
Assert Object / Custom Assertions
Encapsulate complex assertions into reusable methods.
See references/patterns.md for full examples.
Humble Object
When a class mixes logic with infrastructure (I/O, UI, HTTP), extract the logic into a pure testable class. The "humble object" is the thin infrastructure wrapper.
Functional Architecture
Separate pure logic (unit tested) from side effects (integration tested). Pure functions → unit tests. Orchestration → integration tests.
What NOT to Test
- Simple properties / DTOs with no logic
- Constant-returning methods
- Code where the test description is "calls method and returns what I set"
- Private methods directly — test through public behavior
Reference Files
references/patterns.md— Object Mother, Builder, Assert Object examples (multi-language)references/anti-patterns.md— Common mistakes with before/after examplesreferences/test-doubles.md— Fake, Stub, Spy, Mock examples (multi-language)
More from masterfermin02/agent-skills
laravel-money
Use the cknow/laravel-money package for Laravel projects that need to model, persist, cast, format, compare, or calculate money safely. Trigger when working on Laravel apps that handle currency, prices, totals, invoices, billing, checkout, discounts, taxes, balances, monetary casts, or any request mentioning money handling, currency formatting, integer minor units, Money value objects, or 'laravel-money'. Prefer this over raw floats for monetary values in Laravel.
2pr-review
Code review GitHub Pull Requests. Use whenever asked to review a PR, check a pull request, audit a diff, or give feedback on a GitHub PR. Triggers on: 'review this PR', 'code review', 'check this PR', 'review pull request', GitHub PR URLs (github.com/.../pull/NNN), or any request to audit code changes. Supports private repos via GitHub token. Delegates to language-specific skills (laravel-best-practices, csharp-best-practices, php-the-right-way) when applicable.
1frontend-pragmatic-architecture
Apply pragmatic AI-era architecture rules to frontend projects such as React, Next.js, or similar frameworks. Use when organizing pages, features, components, hooks, UI state, and frontend API calls so important logic stays easy to find and changes stay local.
1