Rails中Timecop.travel测试返回false而非true问题求助
问题分析
你的测试失败的核心原因是Timecop修改当前时间后,24.hours.ago的基准也跟着变了,导致你的时间比较逻辑完全搞反了。
我们拆解下测试里的时间线就清楚了:
- 你用
Timecop.travel 2.days.ago把系统当前时间“穿越”到了2天前 - 创建的Message的
created_at就是这个2天前的时刻 - 当你计算
24.hours.ago时,这个值是基于被Timecop修改后的当前时间(也就是2天前),算下来就是2天前 - 24小时 = 3天前 - 最后判断
time_created < 24.hours.ago→ 相当于判断“2天前 < 3天前”,这显然是false,和你预期的true完全相反
解决方案
这里有几种清晰的修复方式,你可以根据习惯选择:
方式1:修正比较逻辑(最简单)
直接计算消息创建时间与当前时间的差值,判断是否超过24小时,这样不管Timecop怎么改时间,逻辑都不会乱:
test "messenger tag is more than 24 hours" do Timecop.travel 2.days.ago account = accounts(:messenger_v2) contact_d = Contact.create! account: account, name: 'Mr Right', phone_number: nil, external_id: '155581474881005', contact_type: 'MessengerV2', source: 'Inbound', is_registered: true, primary_contact: true conversation = Conversation.create! contact: contact_d, account: account, status: 'Open', unread: true, conversation_type: 'Private' Message.create! contact: contact_d, message_type: 'Text', text: 'I have some enquries', direction: 'IN', account: account, conversation: conversation, external_id: "in_a#{Time.now.to_i.to_s}" msg = conversation.messages.incoming time_created = msg.last.created_at # 改成计算时间差是否大于24小时 messenger_tags = (Time.now - time_created) > 24.hours assert_equal true, messenger_tags end
方式2:调整Timecop的使用逻辑(更贴合业务场景)
先穿越到过去创建消息,再回到当前时间做判断,完全模拟真实业务中“消息已超过24小时”的场景:
test "messenger tag is more than 24 hours" do account = accounts(:messenger_v2) contact_d = Contact.create! account: account, name: 'Mr Right', phone_number: nil, external_id: '155581474881005', contact_type: 'MessengerV2', source: 'Inbound', is_registered: true, primary_contact: true conversation = Conversation.create! contact: contact_d, account: account, status: 'Open', unread: true, conversation_type: 'Private' # 穿越到25小时前创建消息,确保超过24小时阈值 Timecop.travel(25.hours.ago) do Message.create! contact: contact_d, message_type: 'Text', text: 'I have some enquries', direction: 'IN', account: account, conversation: conversation, external_id: "in_a#{Time.now.to_i.to_s}" end # 回到当前时间,判断消息是否早于24小时前 msg = conversation.messages.incoming time_created = msg.last.created_at messenger_tags = time_created < 24.hours.ago assert_equal true, messenger_tags end
方式3:手动设置消息创建时间
如果不想用Timecop的复杂穿越,也可以直接给Message指定created_at属性:
test "messenger tag is more than 24 hours" do account = accounts(:messenger_v2) contact_d = Contact.create! account: account, name: 'Mr Right', phone_number: nil, external_id: '155581474881005', contact_type: 'MessengerV2', source: 'Inbound', is_registered: true, primary_contact: true conversation = Conversation.create! contact: contact_d, account: account, status: 'Open', unread: true, conversation_type: 'Private' # 直接把消息创建时间设为24小时1分钟前,确保超过阈值 Message.create! contact: contact_d, message_type: 'Text', text: 'I have some enquries', direction: 'IN', account: account, conversation: conversation, external_id: "in_a#{Time.now.to_i.to_s}", created_at: 24.hours.ago + 1.minute msg = conversation.messages.incoming time_created = msg.last.created_at messenger_tags = time_created < 24.hours.ago assert_equal true, messenger_tags end
内容的提问来源于stack exchange,提问作者Sista-Night




