-
Notifications
You must be signed in to change notification settings - Fork 0
Feature Mock clock
github-actions[bot] edited this page Jul 14, 2026
·
1 revision
Всё, что умеет FrozenClock, плюс виртуальный сон:
sleep() мгновенно сдвигает время вместо блокировки процесса.
MockClock реализует одновременно AdjustableClockInterface и
SleepableClockInterface. Код, который в проде получает SystemClock
и честно спит, в тестах получает MockClock — и «спит» за микросекунды:
use CloudCastle\Clock\MockClock;
$clock = MockClock::from('2026-01-01 00:00:00', 'UTC');
$clock->sleep(3600.0); // мгновенно: время +1 час, процесс не ждёт
$clock->sleepUntil(new DateTimeImmutable('2026-01-01 06:00:00', new DateTimeZone('UTC')));
$clock->now()->format('H:i'); // 06:00sleepUntil() с прошедшим или текущим моментом ничего не меняет — включая
экземпляр момента: часы не подменяют его на переданный.
final class ApiRetrier
{
public function __construct(private readonly SleepableClockInterface $clock) {}
public function call(callable $attempt): mixed
{
foreach ([1.0, 2.0, 4.0] as $backoff) {
try {
return $attempt();
} catch (TransportException) {
$this->clock->sleep($backoff);
}
}
return $attempt();
}
}
// В тесте: MockClock — три ретрая проходят мгновенно,
// и можно проверить, что виртуально прошло ровно 7 секунд.- Тесты retry/backoff/тайм-аутов выполняются за миллисекунды.
- Паритет семантики
sleep()/modify()сSymfony\Component\Clock\MockClockподтверждён интеграционными тестами пакета.
- Виртуальный сон не отдаёт управление другим процессам — для интеграционных
тестов с реальной конкуренцией используйте
SystemClockи короткие паузы.
- Единственные часы в юнит-тестах кода с ожиданиями.
- Совместно с ClockHolder — подмена времени всего приложения одной строкой.
- Реальный
usleep()в тестах «для надёжности» рядом с MockClock — вы теряете весь выигрыш.
flowchart LR
MC[MockClock] --- A[AdjustableClockInterface]
MC --- S[SleepableClockInterface]
A -->|"setTo/modify/advance/rewind"| VT[(виртуальное время)]
S -->|"sleep()/sleepUntil() — без блокировки"| VT
sequenceDiagram
participant T as Тест
participant C as Код с backoff
participant M as MockClock
T->>M: from('2026-01-01', 'UTC')
T->>C: run(clock: M)
loop ретраи 1с, 2с, 4с
C->>M: sleep(N) — мгновенно
M->>M: время += N
end
C-->>T: результат за миллисекунды
T->>M: now() == 00:00:07 ✓
| Возможность | Clock | symfony/clock | lcobucci/clock | beste/clock | nesbot/carbon | ergebnis/clock | 🏆 Победитель |
|---|---|---|---|---|---|---|---|
Виртуальный sleep()
|
✅ | ✅ | ❌ | ❌ | ❌ | ❌ | Clock + symfony/clock |
Виртуальный sleepUntil(момент)
|
✅ | ❌ | ❌ | ❌ | ❌ | ❌ | Clock |
Полный набор setTo/advance/rewind
|
✅ | ❌ | ❌ | ❌ | Clock | ||
| Отдельный тип для тестовых часов | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | Clock + symfony/clock |
CloudCastle Clock · · PHP 8.1+
GitHub · Packagist · Releases · Discussions · Issues
Email · Telegram · VK · Сетка · 💜 Поддержать проект
Исходники Wiki — каталог wiki/ в репозитории (синхронизация через GitHub Actions)