Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TimeWithZone & Time.zone.now integration test fails

In a controller method I set a user's variable activation_sent_at equal to Time.zone.now when an activation email is sent to that user. On the development server this seems to work (although time expressions in my application are 2 hours behind on the local time of my computer).

I want to include an integration test that tests whether activation_sent_at indeed gets set properly. So I included the line:

assert_equal @user.activation_sent_at, Time.zone.now

However, this produces the error:

No visible difference in the ActiveSupport::TimeWithZone#inspect output.
You should look at the implementation of #== on ActiveSupport::TimeWithZone or its members.

I think it's suggesting to use another expression for Time.zone.now in my test. I've looked at different sources, including http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html, but am not sure what to do here. Any suggestions what could be causing this error?

Additional info: Adding puts Time.zone.now and puts @stakeholder.activation_sent_at confirms the two are equal. Not sure what generates the failure/error.

like image 702
Nick Avatar asked Jun 02 '15 18:06

Nick


3 Answers

The issue is that the 2 dates are very close to each other but not the same. You can use assert_in_delta

assert_in_delta @user.activation_sent_at, Time.zone.now, 1.second

For RSpec, a similar approach would be to use be_within:

expect(@user.activation_sent_at).to be_within(1.second).of Time.zone.now

like image 57
AbM Avatar answered Oct 23 '22 05:10

AbM


The problem is that your times are very close but not quite equal. They are probably off by a few fractions of a second.

One solution to issues like this is a testing gem called timecop. It gives you the ability to mock Time.now so that it will temporarily return a specific value that you can use for comparisons.

like image 39
msergeant Avatar answered Oct 23 '22 04:10

msergeant


The reason is because Time.now or Time.zone.now include milliseconds (when you do a simple put to print the time it doesn't show milliseconds). However, when you persist the timestamp in the database these milliseconds likely get lost unless the db field is configured to store milliseconds. So when you read the value from the db it will not include milliseconds, hence the times are slightly different.

One solution is to remove milliseconds from Time.now. You can do this like so Time.now.change(usec: 0). This should fix the error in the tests.

like image 20
user91240192094 Avatar answered Oct 23 '22 03:10

user91240192094