Search code examples
ruby-on-railsrubytimerspeccomparison

Trouble comparing time with RSpec


I am using Ruby on Rails 4 and the rspec-rails gem 2.14. For a my object I would like to compare the current time with the updated_at object attribute after a controller action run, but I am in trouble since the spec does not pass. That is, given the following is the spec code:

it "updates updated_at attribute" do
  Timecop.freeze

  patch :update
  @article.reload
  expect(@article.updated_at).to eq(Time.now)
end

When I run the above spec I get the following error:

Failure/Error: expect(@article.updated_at).to eq(Time.now)

   expected: 2013-12-05 14:42:20 UTC
        got: Thu, 05 Dec 2013 08:42:20 CST -06:00

   (compared using ==)

How can I make the spec to pass?


Note: I tried also the following (note the utc addition):

it "updates updated_at attribute" do
  Timecop.freeze

  patch :update
  @article.reload
  expect(@article.updated_at.utc).to eq(Time.now)
end

but the spec still does not pass (note the "got" value difference):

Failure/Error: expect(@article.updated_at.utc).to eq(Time.now)

   expected: 2013-12-05 14:42:20 UTC
        got: 2013-12-05 14:42:20 UTC

   (compared using ==)

Solution

  • Ruby Time object maintains greater precision than the database does. When the value is read back from the database, it’s only preserved to microsecond precision, while the in-memory representation is precise to nanoseconds.

    If you don't care about millisecond difference, you could do a to_s/to_i on both sides of your expectation

    expect(@article.updated_at.utc.to_s).to eq(Time.now.to_s)
    

    or

    expect(@article.updated_at.utc.to_i).to eq(Time.now.to_i)
    

    Refer to this for more information about why the times are different