- Copy the following code into spec/time_spec_helper.rb
unless Time.respond_to? :real_now # prevent the error: stack level too deep (SystemStackError) # <b>Test Helper: used only in testing!</b> # # Extend the Time class so that we can offset the time that now # returns. This should allow us to effectively time warp for functional # tests that require limits per hour, what not. # # Example usage: # require File.expand_path(File.dirname(__FILE__) '/../spec_helper') # require File.expand_path(File.dirname(__FILE__) '/../time_spec_helper') # # describe YourModel do # # before(:each) do # pretend_now_is(Time.local(1999, 8, 1)) # position *all* tests back in time! # end # # after(:each) do # Time.reset # jump back to the present # end # # it "should be 1999" do # Time.now.year.should == 1999 # end # # # If one particular spec needs some time jumping of its own... # it "should jump to decades" do # pretend_now_is(Time.local(1960)) do # Time.now.year.should == 1960 # end # # pretend_now_is(Time.local(1970)) do # Time.now.year.should == 1970 # end # end # # ... # end # # # <em><tt>(see reference http://snippets.dzone.com/posts/show/1738)</tt></em> class Time class <<self attr_reader :offset alias_method :real_now, :now def now @offset = 0 if @offset.nil? real_now - @offset end alias_method :new, :now # Warp to an absolute time in the past or future, making sure it takes # the present as the reference starting point when making the jump. def set(time) reset @offset = now - time end # Jump back to present. def reset @offset = 0 end end end end # Time warp to the specified time . If given a block, it applies only for the # duration of the passed block. def pretend_now_is(time) Time.set(time) if block_given? begin yield ensure Time.reset end end end
- Require it in your spec:
require File.expand_path(File.dirname(__FILE__) + '/../time_spec_helper')
- Travel through time in your specs:
before(:each) do pretend_now_is(Time.local(1999, 8, 1)) # position *all* tests back in time! end after(:each) do Time.reset # jump back to the present end it "should be 1999" do Time.now.year.should == 1999 end # If one particular spec needs some time jumping of its own... it "should jump to decades" do pretend_now_is(Time.local(1960)) do Time.now.year.should == 1960 end pretend_now_is(Time.local(1970)) do Time.now.year.should == 1970 end end
- Enjoy.
If this was useful for you, please take a minute and recommend me: Thank you!
Comments
rick said...
Why not just use your stubbing library of choice?
Time.stub!(:now).and_return(Time.utc(....))
Johannes Fahrenkrug said...
That's a great idea, Rick!
October 17, 2008 08:31 AMI'd still keep the "pretend_now_is" method, though, since it's so nice and readable, but changing the implementation to take advantage of stubbing will basically bring it down to a one-liner. Nice!