🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano
ClockSensitiveTrait — mocking time in PHPUnit
⚠️ Traduzione preliminare: fa fede la versione russa; il contenuto sottostante è per ora in inglese.
Purpose
A trait for PHPUnit 10+ test cases: mockTime() puts a MockClock into the global clock, unmockTime() removes the substitution, and the #[Before]/#[After] hooks restore the original clock after every test. Parity with symfony ClockSensitiveTrait.
What for and how to use
Tests for code built on ClockHolder/DatePoint/Clock::now(): $clock = self::mockTime('2026-01-01 10:00'); $clock->sleep(60); — no manual global state cleanup.
Example
final class InvoiceTest extends TestCase
{
use ClockSensitiveTrait;
public function testDueDate(): void
{
$clock = self::mockTime('2026-01-01 10:00');
$clock->sleep(86_400); // one virtual day
self::assertSame('2026-01-02', (new DatePoint())->format('Y-m-d'));
}
} // the original clock is restored by the #[After] hook
Anti-patterns
With dependency injection pass a MockClock to the constructor — global substitution is only needed for DI-free code.
Lifecycle
sequenceDiagram
participant P as PHPUnit
participant T as Test + trait
participant H as ClockHolder
P->>T: #[Before] saveClockBeforeTest()
T->>H: remember current clock
P->>T: test method
T->>H: mockTime() sets MockClock
P->>T: #[After] restoreClockAfterTest()
T->>H: reset + restore saved clock
Feature comparison with competitors
| Aspect | 🏆 CloudCastle | symfony | carbon | lcobucci | beste | ergebnis |
|---|---|---|---|---|---|---|
| One-line time mocking in a test | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Clock auto-restore after a test | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
Returns a MockClock to drive time | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| PHPUnit 10+ attributes instead of annotations | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Total | 🏆 4 | 3 | 0 | 0 | 0 | 0 |
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano