在讀這篇文章之前,希望你至少已經:
有時候我們會需要透過時間決定程式的行為,
比如說某抽獎網頁在每天晚上八點之後開放直到十點,
那麼我們撰寫好那段「以時間決定是否放行」的程式之後,
該怎麼測試它是不是能正常運作呢?
這個時候你就會需要 ```setTestNow()``````,
比如說我「現在」執行了底下這行程式碼:
<?php
Carbon::setTestNow(
Carbon::create(2012, 12, 21)
);
// 世界末日
$endOfWorld = Carbon::create(2012, 12, 21);
// 末日當天
if (Carbon::today()->diffInDays(endOfWorld, true) === 0) {
fireBallRains();
storm();
earthquake();
beingFriendzoned();
}
// 重置
Carbon::setTestNow();
那麼 if-else 裡面那些動作就會立即執行。
但如果上面這段程式碼我沒有使用 setTestNow,
那麼我理應會從 Carbon::today()
得到發文日的「2017-12-28」,
那麼也就不會觸發那個 if-else 了。
這樣做的好處很明顯!
你只要在一個地方加上 setTestNow,
那不管是你在哪個 class 呼叫了 Carbon::today()
,都會得到設定給 setTestNow 那天!
所以我們就能透過它模擬程式在某個時間點之後的行為了!
進一部的說,
既然我們能隨意模擬某個時間點,
那麼我們就能做大量的模擬測試了!
大家有興趣的話可以看一下程式碼,其實並不長。
簡單說,
Carbon::today()、Carbon::tomorrow()、Carbon::yesterday(),
上述三者都依賴於 Carbon::now()。
而 Carbon::now() 則僅僅做了 return new static(null, $tz)
,
所以 Carbon::now() 又依賴於 Carbon 的建構子。
在符合 static::hasTestNow() && (empty($time)
時,
建構子就會執行 $testInstance = clone static::getTestNow()
,
並對 $testInstance 執行必要的調整之後回傳~
所以簡單來說,
就是 setTestNow() 執行的結果會直接影響到 __construct() 產生的時間~