← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Test Doubles

testing PHP 8.0+ Intermediate

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');

Added 31 Mar 2026
Views 29
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 1 ping S 0 pings M 2 pings T 1 ping W 1 ping T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T
No pings yesterday
Perplexity 10 Amazonbot 6 SEMrush 4 Google 3 Unknown AI 3 Ahrefs 2
crawler 25 crawler_json 2 pre-tracking 1
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

✓ schema.org compliant