Ruby on rails 如何修复依赖于时间流逝的RSpec测试

Ruby on rails 如何修复依赖于时间流逝的RSpec测试,ruby-on-rails,rspec,Ruby On Rails,Rspec,我的一个控制器中有以下方法: def ping @obj.last_ping_at = DateTime.now @obj.save! end 我想测试这是否有效,因此我编写了以下测试: it 'successfully updates last_ping_at' do old_last_ping_at = obj.last_ping_at patch url(obj) expect(response).to have_http_status(:ok) expect(o

我的一个控制器中有以下方法:

def ping
  @obj.last_ping_at = DateTime.now
  @obj.save!
end
我想测试这是否有效,因此我编写了以下测试:

it 'successfully updates last_ping_at' do
  old_last_ping_at = obj.last_ping_at
  patch url(obj)
  expect(response).to have_http_status(:ok)
  expect(obj.reload.last_ping_at).not_to eql(old_last_ping_at)
end

问题是:时间总是一样的。它改变它的唯一方法是,我添加一个
绑定。撬动控制器方法,然后继续。

最后一次
设置为肯定不是现在,然后检查它是否接近现在


注意:
DateTime。现在
将是计算机上的时区,而不是应用程序的时区。改用
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)> 


有时你不能在
中使用
be\u。在这种情况下,你可以冻结时间。为了鲁比将军。Rails具有内置的

我进一步将其烘焙到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\u 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无论您喜欢显式块还是隐式元数据。

您可以使用
travel
方法:

# 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
it 'successfully updates last_ping_at' do
  old_last_ping_at = obj.last_ping_at

  travel 1.day do
    patch url(obj)
    expect(response).to have_http_status(:ok)
    expect(obj.reload.last_ping_at).not_to eql(old_last_ping_at)
  end
end

讨论对您有帮助吗?
it 'successfully updates last_ping_at' do
  old_last_ping_at = obj.last_ping_at

  travel 1.day do
    patch url(obj)
    expect(response).to have_http_status(:ok)
    expect(obj.reload.last_ping_at).not_to eql(old_last_ping_at)
  end
end