Comparison between two ActiveSupport::TimeWithZone

2019-05-29 09:08发布

问题:

In my test suite, I have a failing test.

expected[0]['date'] comes from SomeModel.first.created_at

In a debugging console, I have the following:

> expected[0]['date']
=> Tue, 25 Mar 2014 16:01:45 UTC +00:00
> res[0]['date']
=> Tue, 25 Mar 2014 16:01:45 UTC +00:00
> res[0]['date'] == expected[0]['date']
=> false # wtf
> res[0]['date'].class
=> ActiveSupport::TimeWithZone
> expected[0]['date'].class
=> ActiveSupport::TimeWithZone
>

How is this possible ?

I've tried to reproduce this problem (I tought maybe the == operator on TimeWithZone checks the reference, or something like this, but no...) :

> t1 = Time.zone.at(0)
=> Thu, 01 Jan 1970 00:00:00 UTC +00:00
> t2 = Time.zone.parse(t1.to_s)
=> Thu, 01 Jan 1970 00:00:00 UTC +00:00
> t1 == t2
=> true
> t1.class
=> ActiveSupport::TimeWithZone
> t2.class
=> ActiveSupport::TimeWithZone

Edit: More tests...

> res[0]['date'].eql?(expected[0]['date'])
=> false
> res[0]['date'].zone
=> "UTC"
> expected[0]['date'].zone
=> "UTC"
> expected[0]['date'].getlocal
=> 2014-03-25 16:01:45 +0000
> res[0]['date'].getlocal
=> 2014-03-25 16:01:45 +0000
> res[0]['date'].hash
=> -3455877575500291788
> expected[0]['date'].hash
=> -3819233736262144515
>
> t1.hash
=> 2279159074362527997
> t2.hash
=> 2279159074362527997

# inspect...
> expected[0]['date'].inspect
=> "Tue, 25 Mar 2014 16:39:01 UTC +00:00"
> res[0]['date'].inspect
=> "Tue, 25 Mar 2014 16:39:01 UTC +00:00"

Looks like the comparison is based on the hash object. Why res and expected have different hashes ?

回答1:

Answer #1 rake db:test:prepare

First, attempt dropping the test database and recreating it, and then running rake db:test:prepare. This has resolved this issue for me in the past I know this is a bit of a lame answer, but it is worth a shot.

Answer #2 Spring + Rspec + Shoulda matchers

If having this issue after installing Spring, please checkout this Github Thread, which can cause tests to fail: https://github.com/rails/spring/issues/209

This issue only started occurring for me after adding Spring to my project. Adding gem 'shoulda', require: false and manually adding require 'shoulda/matchers' to my spec_helper.rb resolved the issues

Answer #3 Timecop

If still having issues, checkout the Timecop gem and freeze time around date comparisons. https://github.com/travisjeffery/timecop