RSpec'ing with Time.now

Wednesday 5 November 2008

I'm currently writing some RSpec tests that use Time.now.

I want my model to calculate a duration and store the future time in the database. I've already specced the calculation of the duration, but I also want to spec that everything gets saved correctly. Here's my first spec:

1
2
3
4
it "should do stuff" do
  m = Model.create()
  m.expires_at.should eql(Time.now + some_value)
end

This fails.

It fails because Time.now is quite accurate and some milliseconds have passed between the two calls.

So how do you test this kind of behaviour? I was not going to let this one beat me. Get out your gloves, because we're going to start stubbing!

What you need to do is stub out Time#now to return a constant value within this test. This way, both calls will use the same Time.now value and thus yield the same result. This in turn makes your test pass (if the saving goes well, of course).

1
2
3
4
5
6
7
it "should do stuff" do
  @time_now = Time.parse("Feb 24 1981")
  Time.stub!(:now).and_return(@time_now)

  m = Model.create()
  m.expires_at.should eql(Time.now + some_value)
end
Did you enjoy this post? Your generosity is much appreciated.