Stubbing Time.zone.now for model tests fails for Rails 2.3.1


#1

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 C. 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 S.
removed_email_address@domain.invalid


#2

On Wed, Mar 11, 2009 at 12:40 PM, David S. removed_email_address@domain.invalid
wrote:

and then to stub the time returned, similar to the method that David
Time.stub!(:zone).and_return(@timezone)
@timezone.stub!(:now).and_return(@new)

How about:

@now = Time.now
@zone = mock(‘timezone’)
@zone.stub!(:now).and_return(@now)
Time.stub!(:zone).and_return(@zone)

Now you’re not depending on TimeZone in the examples. Let us know if it
works.

Cheers,
David


#3

On Wed, Mar 11, 2009 at 1:40 PM, David S. removed_email_address@domain.invalid
wrote:

Has anyone else run into this problem and come up with a solution to getting
a fixed time back from Time.zone.now?

This plugin has worked very well for me:
http://github.com/notahat/time_travel/tree/master


Have Fun,
Steve E. (removed_email_address@domain.invalid)
ESCAPE POD - The Science Fiction Podcast Magazine
http://www.escapepod.org


#4

On 12 mrt 2009, at 04:22, Stephen E. wrote:

On Wed, Mar 11, 2009 at 1:40 PM, David S. removed_email_address@domain.invalid
wrote:

Has anyone else run into this problem and come up with a solution
to getting
a fixed time back from Time.zone.now?

This plugin has worked very well for me:
http://github.com/notahat/time_travel/tree/master

Great! This is exactly what I need for a project I’m working on.
However, I need to run all my tests on a specific date. I’m doing
stuff which is week-based, so “Tomorrow” and “Next week” are always
different, and therefore I’d like to set it to a specific date for all
my tests.
Any idea how to hook this into a Before-hook in Cucumber perhaps?

thanks,
bartz


#5

On 14 mrt 2009, at 11:27, Bart Z. wrote:

This plugin has worked very well for me:
http://github.com/notahat/time_travel/tree/master

Great! This is exactly what I need for a project I’m working on.
However, I need to run all my tests on a specific date. I’m doing
stuff which is week-based, so “Tomorrow” and “Next week” are always
different, and therefore I’d like to set it to a specific date for
all my tests.
Any idea how to hook this into a Before-hook in Cucumber perhaps?

While I was doing the dishes, I came up with the following:

World do |world|
at_time(Time.utc(2009,1,1)) do
world
end
end

Unfortunately, this doesn’t work :(…
Any ideas?

thanks a bunch,
bartz