将last_ping_at 设置为绝对不是现在的值,然后使用be_within 检查它是否接近现在。
it 'successfully updates last_ping_at' do
obj.update!(last_ping_at: 1.day.ago)
patch url(obj)
expect(response).to have_http_status(:ok)
expect(obj.reload.last_ping_at).to be_within(1.second).of(DateTime.now)
end
注意:DateTime.now 将是您机器上的时区,而不是应用程序的时区。请改用DateTime.current。
[4] pry(main)> Time.zone = "Fiji"
=> "Fiji"
[5] pry(main)> DateTime.now
=> Thu, 21 Jan 2021 12:13:14 -0800
[6] pry(main)> DateTime.current
=> Fri, 22 Jan 2021 08:13:16 +1200
[7] pry(main)>
见It's About Time (Zones)。
有时您不能使用be_within。在这种情况下,您可以冻结时间。对于一般 Ruby use timecop as @max says。 Rails 内置了 travel_to。
it 'successfully updates last_ping_at' do
travel_to Time.current do
patch url(obj)
expect(response).to have_http_status(:ok)
expect(obj.reload.last_ping_at).to eq Time.current
end
end
我更进一步,将其烘焙到 rspec 元数据中。
# spec/support/config/travel_to.rb
RSpec.configure do |config|
config.around do |example|
if example.metadata[:travel_to]
travel_to example.metadata[:travel_to] do
example.run
end
else
example.run
end
end
end
现在您可以在任何 RSpec 块中travel_to: Time.current。
it 'successfully updates last_ping_at', travel_to: Time.current do
patch url(obj)
expect(response).to have_http_status(:ok)
expect(obj.reload.last_ping_at).to eq Time.current
end
YMMV,无论您更喜欢显式块还是隐式元数据。