Neil
Neil

Reputation: 5178

How to stub out Date that is implicitly referenced by years.ago in RSpec?

I know that I can stub out a method on Date like so:

allow(Date).to receive(:today).and_return Date.new(2015,11,10)

So now if within my spec the code calls Date.today I can be assured that it will return a Date object with the value of 11/10/2015.

I have a scope that utilizes years.ago.to_date. The user specifies the number of years ago for the scope: Ex: 5.years.ago, 2.years.ago.

I am trying to test this scope. In order to do so I need to control the Date that years.ago is referencing. For instance, I would always want the Date to be 1/1/2010. This way I will know that 5.years.ago will return 1/1/2005, and 2.years.ago would return 1/1/2008.

The issue is that I do not know what to stub out. I do not know how to keep the Date consistent which years.ago uses.

Hopefully this makes sense. I just need to control the Date that years.ago uses. How can I stub that out?

I looked a bit at ActiveSupport::Duration, but I'm not sure if that is the right place to look.

Upvotes: 1

Views: 758

Answers (2)

Dave Schweisguth
Dave Schweisguth

Reputation: 37627

You can usually control what Ruby and Rails use for the current time by stubbing Time.now:

allow(Time).to receive(:now).and_return(Time.local 2016, 9, 6, 16, 51)

That does work for years.ago.

If your code, or the framework code you use, uses both Time.now and Date.today, however, timecop is easier.

If you use timecop, be aware that it's easy to forget to Timecop.return, which can screw up subsequent tests. Prefer timecop's safe mode.

Upvotes: 1

Dharam Gollapudi
Dharam Gollapudi

Reputation: 6438

You should check timecop

Then in your tests, you could freeze the date to your desired value as follows:

describe "some set of tests to mock" do
  before do
    Timecop.freeze(2010, 1, 1)
  end

  after do
    Timecop.return
  end

  it "should do blah blah blah" do
  end
end

Upvotes: 4

Related Questions