【问题标题】:TimeWithZone & Time.zone.now integration test failsTimeWithZone 和 Time.zone.now 集成测试失败
【发布时间】:2015-06-02 18:44:49
【问题描述】:

在控制器方法中,当向该用户发送激活电子邮件时,我将用户变量 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 确认两者相等。不确定是什么导致了失败/错误。

【问题讨论】:

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


    【解决方案1】:

    问题是这两个日期彼此非常接近,但并不相同。你可以使用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

    【讨论】:

      【解决方案2】:

      问题是您的时间非常接近,但并不完全相等。它们可能相差几分之一秒。

      解决此类问题的一个方法是使用名为 timecop 的测试 gem。它使您能够模拟 Time.now,以便它暂时返回一个特定值,您可以使用该值进行比较。

      【讨论】:

      • 很有趣,Timecop 是我遇到这个问题时想到的第一个救星,但它没有帮助。好笑。
      • 问题是,即使你冻结了时间,它也无济于事——可能是因为一些无限小的漂移,无论什么算法都无法可靠地比较。但是,当我将时间设置为我选择的特定时刻并舍入毫秒时,它会起作用,即Timecop.freeze 失败并且Timecop.freeze Time.parse("2016-09-13 18:26:09 +0200") 起作用`
      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-29
        • 2019-12-26
        • 1970-01-01
        • 1970-01-01
        • 2017-07-02
        • 2014-09-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多