Our application has some code to schedule recurring tasks, with code
to skip holidays and weekends.
In order to test the schedule model we need to have a fixed time
returned when the model is run so that the tests will run the same no
matter what day they are run. (The first set of tests written would
all pass until run on a weekend, when the skip code would schedule a
task days later in order to skip a weekend day.)
Our solution under Rails 2.1 was to set an instance variable to a
fixed time and then to stub the time returned, similar to the method
that David Chelimsky recommended:
now = Time.now
Time.stub!(:now).and_return(now)
However, our app is using Time.zone.now in order to return local time
in the user's local time zone. The following code works in Rails 2.1:
@now = Time.now
@timezone = TimeZone.new('UTC')
Time.stub!(:zone).and_return(@timezone)
@timezone.stub!(:now).and_return(@new)
In Rails 2.1 this properly returned @now when the model accessed
Time.zone.now.
After upgrading to Rails 2.3.1 (and RSpec 1.1.99.12) *all* tests that
use this method fail. They appear to fail as soon as a time from
Time.zone.now is saved to a model and then accessed, even though the
time in the record appears fine.
The error we're getting is:
"You have a nil object when you didn't expect it!
The error occurred while evaluating nil.period_for_utc"
If I comment out the last two lines above ("Time.stub!" and
"@timezone.stub!") then I don't get that error, but without fixed
times some of our tests fail due to the variable time.
Has anyone else run into this problem and come up with a solution to
getting a fixed time back from Time.zone.now?
David Schmidt
davids at tower-mt.com