Керувати часом застосунку з тесту, а не чекати.
it('expires a subscription after 30 days', function () {
$this->freezeTime();
$subscription = Subscription::factory()->create();
$this->travel(31)->days();
expect($subscription->fresh()->isExpired())->toBeTrue();
});
Інструменти:
freezeTime()- зупиняєnow(), щоб час не зсувався між рядками тесту.travel(5)->minutes(),travelTo($date),travelBack()- зсувають час застосунку.- Те саме вміє
Carbon::setTestNow().
Що варто винести з цього: такий тест працює, лише поки код бере час через now() чи Carbon. Виклики time(), date() чи new \DateTime() бачать справжній годинник і тест обійдуть.
Чистіший шлях для доменного коду - передавати момент явно:
public function isExpired(CarbonImmutable $now): bool
{
return $this->ends_at->lessThan($now);
}
Тоді тест взагалі не потребує підміни часу, а метод стає чистою функцією. Корисні випадки для перевірки: межі (рівно 30 днів), перехід доби, часові пояси й літній час.