Test Doubles
Also Known As
mock
stub
spy
fake
dummy
PHPUnit mock
TL;DR
Substitute objects used in tests to replace real dependencies — mocks, stubs, spies, fakes, and dummies each serve a different purpose.
Explanation
Stub: returns predefined values, no assertions. Mock: verifies interactions (was a method called, how many times, with what args). Spy: records calls for later assertion. Fake: a simplified but working implementation (e.g. in-memory database). Dummy: passed but never used, just to satisfy a parameter. PHPUnit provides mock objects via createMock() and createStub(). Mockery offers a more expressive DSL. Overusing mocks leads to tests that pass even when the real integration is broken.
Common Misconception
✗ More mocks equals better tests. Over-mocking produces tests that verify implementation details rather than behaviour — they break on every refactor and give false confidence.
Why It Matters
Without test doubles, unit tests depend on real databases, APIs, and filesystems — making them slow, brittle, and environment-dependent. Doubles isolate the unit under test.
Common Mistakes
- Mocking third-party libraries directly — wrap them in an adapter and mock the adapter instead.
- Using mocks where a fake (in-memory implementation) would give more realistic test coverage.
- Asserting on mock interactions instead of observable outputs — testing how rather than what.
Avoid When
- Do not mock value objects or simple data structures — instantiate them directly.
- Avoid mocking third-party libraries — wrap them in your own interface and mock that instead.
When To Use
- Use stubs when you need a dependency to return a specific value without caring how it was called.
- Use mocks when the interaction itself (method called, args, times) is the behaviour under test.
Code Examples
✗ Vulnerable
// Mocking a third-party class directly — fragile, couples to implementation
$guzzle = $this->createMock(\GuzzleHttp\Client::class);
$guzzle->method('request')->willReturn(new Response(200, [], 'ok'));
// Better: mock your own HttpClientInterface that wraps Guzzle
✓ Fixed
// Stub: provide a return value
$mailer = $this->createStub(MailerInterface::class);
$mailer->method('send')->willReturn(true);
// Mock: verify interaction
$mailer = $this->createMock(MailerInterface::class);
$mailer->expects($this->once())
->method('send')
->with($this->equalTo('user@example.com'));
$service = new UserService($mailer);
$service->registerUser('user@example.com');
References
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
31 Mar 2026
Views
29
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
No pings yesterday
Perplexity 10
Amazonbot 6
SEMrush 4
Google 3
Unknown AI 3
Ahrefs 2
Also referenced
How they use it
crawler 25
crawler_json 2
pre-tracking 1
Related categories
⚡
DEV INTEL
Tools & Severity
⚙ Fix effort: Medium
⚡ Quick Fix
Use createMock() for verifying interactions, createStub() for providing return values — never mock what you don't own
📦 Applies To
PHP 8.0+
cli
phpunit
phpspec
🔗 Prerequisites
🔍 Detection Hints
createMock() on third-party class or concrete class without interface
Auto-detectable:
✗ No
⚠ Related Problems
🤖 AI Agent
Confidence: Low
False Positives: High
✗ Manual fix
Fix: High
Context: File
Tests: Regenerate