[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Stubbing Time.now with Mocha

Jay Levitt

9/5/2006 9:24:00 PM

Mocha seems a great way to stub Time.now for testing expiration dates, etc.
with rspec. I can get it to stub a single time easily:

Time.stubs(:now).returns(Time.at(1))

but what I'd really like to do is do that multiple times during a test:

specify "with an expired cookie should return nil"
Time.stubs(:now).returns(Time.parse("Jan 1 2001"))
louie.login
cookie = louie.remember_me

Time.stubs(:now).returns(Time.parse("Oct 1 2001"))
louie.login_with_cookie(cookie).should_be_nil
end

However, only the first stubs call has any effect. I've tried stubbing it
to a FakeTime object:

Time.stubs(:now).returns(FakeTime.now)

but it only looks at the value of FakeTime.now when the stub is created.
Is there a way using Mocha/Stubba to stub a routine and have it call
another for the return value? I've tried creating procs/lambdas, but I
must be doing something wrong - I get an infinite recursion.

Jay Levitt
2 Answers

Pete Yandell

9/5/2006 11:21:00 PM

0

Jay,

I don't know about Mocha, but you have to be a bit careful about
replacing Time.now because the test timings depend on it. The way I
do it is as follows. First, I've got a little plugin that includes this:

class Time
@@now = nil

def self.now=(time)
@@now = time
end

def self.forced_now #:nodoc:
@@now || unforced_now
end

class << self
alias_method :unforced_now, :now
alias_method :now, :forced_now
end
end

and then in my test helper:

def at_time(time)
time = Time.parse(time + ' UTC') unless time.instance_of?(Time)
Time.now = time
begin
yield
ensure
Time.now = nil
end
end

That lets me do something like this in a test:

def test_whatever
at_time("Jan 1 2001") do
# Tests go in here.
end
end

Hope that helps!

Cheers,

Pete Yandell


On 06/09/2006, at 7:25 AM, Jay Levitt wrote:

> Mocha seems a great way to stub Time.now for testing expiration
> dates, etc.
> with rspec. I can get it to stub a single time easily:
>
> Time.stubs(:now).returns(Time.at(1))
>
> but what I'd really like to do is do that multiple times during a
> test:
>
> specify "with an expired cookie should return nil"
> Time.stubs(:now).returns(Time.parse("Jan 1 2001"))
> louie.login
> cookie = louie.remember_me
>
> Time.stubs(:now).returns(Time.parse("Oct 1 2001"))
> louie.login_with_cookie(cookie).should_be_nil
> end
>
> However, only the first stubs call has any effect. I've tried
> stubbing it
> to a FakeTime object:
>
> Time.stubs(:now).returns(FakeTime.now)
>
> but it only looks at the value of FakeTime.now when the stub is
> created.
> Is there a way using Mocha/Stubba to stub a routine and have it call
> another for the return value? I've tried creating procs/lambdas,
> but I
> must be doing something wrong - I get an infinite recursion.
>
> Jay Levitt
>


Pete Yandell

9/5/2006 11:47:00 PM

0

Oops...not paying attention to which list I was reading, so my answer
was Rails-specific! The code still applies though, and still has the
advantage of restoring time to normality once you're done.

Pete Yandell

On 06/09/2006, at 9:21 AM, Pete Yandell wrote:

> Jay,
>
> I don't know about Mocha, but you have to be a bit careful about
> replacing Time.now because the test timings depend on it. The way I
> do it is as follows. First, I've got a little plugin that includes
> this:
>
> class Time
> @@now = nil
>
> def self.now=(time)
> @@now = time
> end
>
> def self.forced_now #:nodoc:
> @@now || unforced_now
> end
>
> class << self
> alias_method :unforced_now, :now
> alias_method :now, :forced_now
> end
> end
>
> and then in my test helper:
>
> def at_time(time)
> time = Time.parse(time + ' UTC') unless time.instance_of?(Time)
> Time.now = time
> begin
> yield
> ensure
> Time.now = nil
> end
> end
>
> That lets me do something like this in a test:
>
> def test_whatever
> at_time("Jan 1 2001") do
> # Tests go in here.
> end
> end
>
> Hope that helps!
>
> Cheers,
>
> Pete Yandell
>
>
> On 06/09/2006, at 7:25 AM, Jay Levitt wrote:
>
>> Mocha seems a great way to stub Time.now for testing expiration
>> dates, etc.
>> with rspec. I can get it to stub a single time easily:
>>
>> Time.stubs(:now).returns(Time.at(1))
>>
>> but what I'd really like to do is do that multiple times during a
>> test:
>>
>> specify "with an expired cookie should return nil"
>> Time.stubs(:now).returns(Time.parse("Jan 1 2001"))
>> louie.login
>> cookie = louie.remember_me
>>
>> Time.stubs(:now).returns(Time.parse("Oct 1 2001"))
>> louie.login_with_cookie(cookie).should_be_nil
>> end
>>
>> However, only the first stubs call has any effect. I've tried
>> stubbing it
>> to a FakeTime object:
>>
>> Time.stubs(:now).returns(FakeTime.now)
>>
>> but it only looks at the value of FakeTime.now when the stub is
>> created.
>> Is there a way using Mocha/Stubba to stub a routine and have it call
>> another for the return value? I've tried creating procs/lambdas,
>> but I
>> must be doing something wrong - I get an infinite recursion.
>>
>> Jay Levitt
>>
>
>