Stubbing Time.now with Mocha

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 L.

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 Y.

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 Y.

You can use Mocha to do what you want…

def test_me
time_now = Time.parse(“Jan 1 2001”)
Time.stubs(:now).returns( lambda { time_now } )
assert_equal Time.parse(“Jan 1 2001”), Time.now
time_now = Time.parse(“Oct 1 2001”)
assert_equal Time.parse(“Oct 1 2001”), Time.now
end

The test times should be unaffected. The Time class should get put back
to
normal in the test teardown.

For any other questions on Mocha, it’s probably better to use the
mailing
list - http://rubyforge.org/mailman/listinfo/mocha-developer


James.