两个ActiveSupport :: TimeWithZone对象之间的比较失败

在我的测试套件中,我有一个失败的测试。

expected[0]['date']来自SomeModel.first.created_at

在调试控制台中,我有以下内容:

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

这怎么可能 ?

我试图重现这个问题(我想也许在TimeWithZone上的==运算符检查引用,或类似的东西,但没有……):

 > 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 

编辑 :更多测试……

 > 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" 

看起来比较基于哈希对象。 为什么res和expect有不同的hash

答案#1 rake db:test:prepare

首先,尝试删除测试数据库并重新创建它,然后运行rake db:test:prepare 。 这对我来说已经解决了这个问题,我知道这是一个蹩脚的答案,但值得一试。

回答#2 Spring + Rspec + Shoulda匹配器

如果在安装Spring之后出现此问题,请检查此Github线程,这可能导致测试失败: https : //github.com/rails/spring/issues/209

在将Spring添加到我的项目后,这个问题才开始发生。 添加gem 'shoulda', require: false并手动向我的spec_helper.rb添加require 'shoulda/matchers' spec_helper.rb require 'shoulda/matchers' spec_helper.rb require 'shoulda/matchers'解决了问题

回答#3 Timecop

如果仍有问题,请查看Timecop gem并冻结日期比较时间。 https://github.com/travisjeffery/timecop