如何在 rspec 3 中存根 Date.today.strftime?

How to stub Date.today.strftime in rspec 3?

我有以下代码:

  def when_to_change
    year, month = Date.today.strftime("%Y %m").split(' ').map {|v| v.to_i}
    if month < 9
      year + 2
    else 
      year + 3
    end
  end

我尝试通过以下方式将其存入我的规范中:

  it 'when current month at the of a year' do
    allow(Date.today).to receive(:strftime).with('%Y %m').and_return('2015 10')
    expect(@car.when_to_change).to eq(2018)
  end

  it 'when current month earlier than september' do 
    allow(Date.today).to receive(:strftime).with('%Y %m').and_return('2015 07')
    expect(@car.when_to_change).to eq(2017)
  end

当我尝试 运行 规格时,它看起来不是那样的。我做错了什么?

我用rspecv3.3.2

ANSWER

因为 Date.today returns 每次方法调用都会新建一个对象,这可以通过以下方式完成:

  it 'when current month earlier than september' do 
     allow(Date).to receive(:today).and_return(Date.new(2015, 7, 19))
     expect(@car.when_to_change).to eq(2017)
  end

感谢@DmitrySokurenko 的解释。

Date.today 总是 return 个新对象。首先存根 today

我的意思是:

>> Date.today.object_id
=> 70175652485620
>> Date.today.object_id
=> 70175652610440

因此,当您下次调用 today 时,那是一个不同的对象。

因此,要么将 Date.today 存根到 return 某个固定日期,要么更改您的代码以使用类似 SomeHelper.today 的内容,这将始终 return 在测试中使用相同的日期环境。

我认为 timecop 正是您所需要的。

你不需要 Timecop 来做那件事。 Rails 已经内置了类似的东西:

http://api.rubyonrails.org/classes/ActiveSupport/Testing/TimeHelpers.html

# spec/rails_helper.rb
config.include ActiveSupport::Testing::TimeHelpers

然后:

travel_to(Date.parse('2015-10-01')) do
  expect(@car.when_to_change).to eq(2018)
end