Ruby on rails 如何在运行rails测试时覆盖Date.today?

Ruby on rails 如何在运行rails测试时覆盖Date.today?,ruby-on-rails,ruby,rake,Ruby On Rails,Ruby,Rake,我有一些测试在特定日期失败,因为有人编写它们来使用Date.today。我想重现以前选定日期的故障 有没有一种方法可以使用ENV变量运行rake测试,该变量将覆盖系统时钟?因此,调用Date.today、Time.now和1.day.ago和1.day.from\u now将使用我设置的日期 例如: > DATE_TODAY='2017-01-04' rake test 对于测试您可以使用gem。 它提供了两种有用的方法Timecop.freeze和Timecop.travel 例如,您

我有一些测试在特定日期失败,因为有人编写它们来使用
Date.today
。我想重现以前选定日期的故障

有没有一种方法可以使用ENV变量运行rake测试,该变量将覆盖系统时钟?因此,调用
Date.today
Time.now
1.day.ago
1.day.from\u now
将使用我设置的日期

例如:

> DATE_TODAY='2017-01-04' rake test

对于测试您可以使用gem。 它提供了两种有用的方法
Timecop.freeze
Timecop.travel

例如,您可以使用
freeze
在挂钩之前的中静态设置时间:

describe 'your tests' do
  before do
    Timecop.freeze(Time.new(2017, 1, 4))
  end

  after do
    Timecop.return
  end

  it 'should do something' do
    sleep(10)
    Time.now # => 2017-01-04 00:00:00
  end
end
Timecop.freeze(Time.now - 3.months) do
  assert product.expired?
end
或在块中

describe 'your tests' do
  before do
    Timecop.freeze(Time.new(2017, 1, 4))
  end

  after do
    Timecop.return
  end

  it 'should do something' do
    sleep(10)
    Time.now # => 2017-01-04 00:00:00
  end
end
Timecop.freeze(Time.now - 3.months) do
  assert product.expired?
end
使用
travel
方法时,您可以更改开始时刻,但时间仍然在流逝

Timecop.travel(Time.new(2017, 1, 4))
sleep(10)
Time.now # => 2017-01-04 00:00:10

从Rails 4.1开始,您可以

travel_to Time.new(2004, 11, 24, 01, 04, 44)

完整的API文档在这里:

如果您使用的是Rails
v4.1+
,那么现在就有了内置的——这可能(至少对于这样的简单场景)使得合并第三方库(如
TimeCop
变得不必要了。@TomLord请给出答案。我使用它,而且它很棒。@TomLord注意到DateTime.now在Rails 5之前不支持时间旅行。我相信这个答案(以及Timecop本身)已经过时了,因为Rails已经有了
时间助手。我建议改为。谢谢,知道这一点很高兴,尽管我使用的是Rails 4