Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I want to create test data for an application, and there are a lot of time_at attributes being tracked, too many to override in a maintainable way. What I'm thinking is, can I just change the base reference time variable in Ruby?

This would make it so created_at, updated_at, last_login_at, etc., could be set to an artificial time, so I could do this 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 a way to do this?

like image 913
Lance Avatar asked Dec 04 '22 10:12

Lance


2 Answers

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

Time.stubs(:now).returns(Time.now - 1.day)
like image 89
Pan Thomakos Avatar answered Dec 30 '22 05:12

Pan Thomakos


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

Ex.

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

Its nicer than the mocha solution since all time functions will be affected equally, so you won't have a test where Time.now is returning something different then DateTime.now

Its also more up-to-date than the time-warp gem suggested in another answer.

like image 20
Nate914375 Avatar answered Dec 30 '22 04:12

Nate914375