TimeWithZone& Time.zone.now集成测试失败

时间:2015-06-02 18:44:49

标签: ruby-on-rails ruby ruby-on-rails-4 integration-testing

在控制器方法中,当向该用户发送激活电子邮件时,我将用户的变量activation_sent_at设置为等于Time.zone.now。在开发服务器上,这似乎有效(尽管我的应用程序中的时间表达式在我的计算机的本地时间落后2小时)。

我想要包含一个集成测试,用于测试activation_sent_at是否确实正确设置。所以我加入了这一行:

assert_equal @user.activation_sent_at, Time.zone.now

然而,这会产生错误:

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

我认为它建议在我的测试中使用Time.zone.now的另一个表达式。我查看了不同的来源,包括http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html,但我不知道该怎么做。可能导致此错误的任何建议?

其他信息:添加puts Time.zone.nowputs @stakeholder.activation_sent_at确认两者相同。不确定是什么导致失败/错误。

3 个答案:

答案 0 :(得分:24)

问题是两个日期彼此非常接近但不一样。您可以使用assert_in_delta

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

对于 RSpec ,类似的方法是使用be_within

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

答案 1 :(得分:2)

问题是你的时间非常接近但不完全相同。它们可能会在几分之一秒内消失。

这类问题的一个解决方案是名为timecop的测试宝石。它使您能够模拟Time.now,以便它临时返回可用于比较的特定值。

答案 2 :(得分:1)

原因是因为Time.nowTime.zone.now包含毫秒(当您执行简单的put来打印不显示毫秒的时间时)。但是,当您在数据库中保留时间戳时,除非将db字段配置为存储毫秒,否则这些毫秒可能会丢失。因此,当您从数据库读取值时,它将不包含毫秒,因此时间略有不同。

一种解决方案是从Time.now中删除毫秒。您可以像Time.now.change(usec: 0)这样来做。这应该可以修复测试中的错误。