Rails - 测试使用DateTime.now的方法

rap*_*tle 18 datetime rspec ruby-on-rails timecop ruby-on-rails-4

我有一个方法,使用DateTime.now来执行一些数据的搜索,我想测试具有各种日期的方法,但我不知道如何存根DateTime.now也不能让它使用Timecop(如果它甚至像那样工作).

随着时间的警察我试过

it 'has the correct amount if falls in the previous month' do
      t = "25 May".to_datetime
      Timecop.travel(t)
      puts DateTime.now

      expect(@employee.monthly_sales).to eq 150
end 
Run Code Online (Sandbox Code Playgroud)

当我运行规范时,我可以看到放置DateTime.now 2015-05-25T01:00:00+01:00但是在我正在测试输出2015-07-24T08:57:53+01:00(今天的日期)的方法中使用相同的DateTime.now .我怎么能做到这一点?

------------------更新------------------------------- --------------------

我在一个before(:all)块中设置了记录(@employee等),这似乎导致了问题.它仅在Timecop do块之后完成设置时才有效.为什么会这样?

ami*_*hle 12

TL; DR:问题是,DateTime.now被称为在Employee之前Timecop.freeze已经调用了规范.

时空特警嘲笑的构造Time,DateDateTime.在模拟之间freezereturn(或在freeze块内)创建的任何实例都将被模拟.
之前freeze或之后创建的任何实例return都不会受到影响,因为Timecop不会混淆现有对象.

README(我的重点):

提供"时间旅行"和"时间冻结"功能的宝石,使得测试依赖于时间的代码变得简单.它提供了一个统一的方法来在一次调用中模拟Time.now,Date.today和DateTime.now.

因此,Timecop.freeze在创建Time要模拟的对象之前调用是至关重要的.如果您freeze在RSpec before块中,这将在subject评估之前运行.但是,如果您有一个before块来设置主题(@employee在您的情况下),并且before在嵌套中有另一个块describe,则您的主题已经设置,DateTime.new在您冻结时间之前已经调用.


如果您将以下内容添加到您的帐户会发生什么 Employee

class Employee
  def now
    DateTime.now
  end
end
Run Code Online (Sandbox Code Playgroud)

然后运行以下规范:

describe '#now' do
  let(:employee) { @employee }
  it 'has the correct amount if falls in the previous month', focus: true do
    t = "25 May".to_datetime
    Timecop.freeze(t) do
      expect(DateTime.now).to eq t
      expect(employee.now).to eq t

      expect(employee.now.class).to be DateTime
      expect(employee.now.class.object_id).to be DateTime.object_id
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

而不是使用一个freeze块,你也可以freezereturn在RSpec中beforeafter挂钩:

describe Employee do
  let(:frozen_time) { "25 May".to_datetime }
  before { Timecop.freeze(frozen_time) }
  after { Timecop.return }
  subject { FactoryGirl.create :employee }

  it 'has the correct amount if falls in the previous month' do
    # spec here
  end

end
Run Code Online (Sandbox Code Playgroud)

偏离主题,但也许看看http://betterspecs.org/