Override what Ruby considers current time in Time.now?

I want to create test data for the application, and there are many time_at attributes that are tracked, too much to override in a supported way. What I mean is, can I just change the base reference time variable in Ruby?

It would do this: created_at , updated_at , last_login_at , etc., it would be possible to set artificial time, so I could do it in tests:

 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 

Is there any way to do this?

+4
source share
5 answers

You can use Mocha to change the return value of Time.now during the test:

  Time.stubs (: now) .returns (Time.now - 1.day)
+7
source

A good stone for this is Timecop: https://github.com/travisjeffery/timecop .
You can freeze time or change the time (as long as it continues to evolve) very easily.

Ref.

 Time.now # => 2014-03-14 13:17:02 -0400 Timecop.travel 2.hours.ago Time.now # => 2014-03-14 11:17:04 -0400 

This is better than a mocha solution, since all time functions will be affected equally, so you will not have a test where Time.now returns something other than DateTime.now

It is also more modern than a time-based gem in a different answer.

+4
source

I use a timewarp gem for this kind of thing. You simply put your code in the pretend_now_is (time) block, and the code inside will be executed as if it were the actual time.

http://github.com/harvesthq/time-warp

Here is an example

 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 
+3
source

Honestly, I usually write tests for the current time to check if the timestamp is in a reasonable range. that is, check if the timestamp exceeds 1.minute.ago . Changing the system clock is likely to have all kinds of unpredictable side effects, so you don’t want to do this. You could keep track of all the places in Ruby that the current time is accessing (although I think most methods only use Time.now ) and monkey patch them for tests, but I probably still prefer to just check the timestamp is within a reasonable range.

+1
source

It is also possible (yuck) monkeypatch Time:

 $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) 
+1
source

Source: https://habr.com/ru/post/1333837/


All Articles