簡體   English   中英

覆蓋Ruby認為Time.now中的當前時間?

[英]Override what Ruby thinks is the current time in Time.now?

我想為應用程序創建測試數據,並且有很多time_at屬性被跟蹤,太多而無法以可維護的方式覆蓋。 我在想的是,我可以在Ruby中更改基准參考時間變量嗎?

這樣就可以將created_atupdated_atlast_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM