[英]Override what Ruby thinks is the current time in Time.now?
我想為應用程序創建測試數據,並且有很多time_at
屬性被跟蹤,太多而無法以可維護的方式覆蓋。 我在想的是,我可以在Ruby中更改基准參考時間變量嗎?
這樣就可以將created_at
, updated_at
, last_login_at
等設置為一個人工時間,所以我可以在測試中這樣做:
Date.today #=> Thu, 30 Dec 2010
Time.system_time_offset = 1.week.ago # made up
Date.today #=> Thu, 23 Dec 2010
Time.now #=> Thu Dec 23 14:08:38 -0600 2010
user_1 = User.create!
user_1.created_at #=> Thu Dec 23 14:08:38 -0600 2010
Time.reset_system_time # made up
user_2 = User.create!
user_1.created_at #=> Thu Dec 30 14:08:38 -0600 2010
有沒有辦法做到這一點?
您可以使用Mocha在測試期間更改Time.now的返回值:
Time.stubs(:now).returns(Time.now - 1.day)
一個很好的寶石是Timecop: https : //github.com/travisjeffery/timecop 。
您可以非常輕松地凍結時間或更改時間(同時繼續進行)。
防爆。
Time.now
# => 2014-03-14 13:17:02 -0400
Timecop.travel 2.hours.ago
Time.now
# => 2014-03-14 11:17:04 -0400
它比mocha解決方案更好,因為所有時間函數都會受到同等影響,所以你不會有一個測試,其中Time.now返回的東西與DateTime.now不同。
它也比另一個答案中提出的時間扭曲寶石更新。
我使用timewarp gem來做這類事情。 您只需將代碼放在pretend_now_is(時間)塊中,內部代碼將被執行,就像實際時間一樣。
http://github.com/harvesthq/time-warp
這是一個例子
def test_should_find_company_needing_reminded_today
pretend_now_is(Time.utc(2008,"jul",24,20)) do #=> Thu Jul 24 20:00:00 UTC 2008
@company.reminder_day = 'Thursday'
@company.save
companies = Company.find_companies_needing_reminded_today
assert_equal true, companies.include?(@company)
end
end
老實說,我通常會編寫當前時間的測試來檢查時間戳是否在合理的范圍內。 即,檢查時間戳是否大於1.minute.ago
。 更改系統時鍾可能會產生各種不可預測的副作用,因此您不希望這樣做。 您可以跟蹤Ruby中訪問當前時間的所有位置(雖然我認為大多數方法只使用Time.now
)並對測試進行猴子修補,但我可能仍然更喜歡只檢查時間戳在一個理智的范圍內。
它也可能(yuck)monkeypatch時間:
$start = Time.now - 86400 # this time yesterday
class Time
class << Time
def new
$start
end
def now
Time.new
end
end
end
puts(Time.now)
puts($start)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.