Stubbing Time.Now with Rspec

Stubbing Time.now with RSpec

Depending on your version of RSpec you might want to use the newer syntax:

allow(Time).to receive(:now).and_return(@time_now)

See RSpec Mocks 3.3

How to stub Time.now.hour

Another approach would be to use Timecop (or the new Rails replacement travel_to) to stub out your time for you. With Timecop you can have super readable specs with no need for manual stubbing:

# spec setup

Timecop.freeze(Time.now.beginning_of_day + 11.hours) do
visit root_path
do_other_stuff!
end

RSpec Stubbing out Date.today in order to test a method

Add this to your before block.

allow(Date).to receive(:today).and_return Date.new(2001,2,3)

I *think* it is not necessary to unstub.

What is the best way to stub date in spec?

You can use Timecop:
It provides very simple way to freeze time at any point you want, for example:

describe "#sales_by_week" do
before { Timecop.freeze(Time.now.beginning_of_week+6.days) }

it "returns the number of sale by week" do
create(:sale, created_at: 2.weeks.ago)
create(:sale, created_at: 3.days.ago)
create(:sale, created_at: Date.today )

res = subject.sales_by_week

expect(res.values.last).to eq(2)
end
end

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

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

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

Date.today always return new objects. Stub the today at first.

I mean that:

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

So when you call the today next time, that's a different object.

Thus either stub the Date.today to return some fixed date, either change your code to use something like SomeHelper.today which will always return the same date in test environment.

Stubbing tomorrow's date in rspec

The issue is that the times might look exactly the same, but the timestamps aren't, the time which is spent between running the two statements ( even if it's in micro seconds ) makes the time different, to solve it you should use the same time variable in both statements, for example:

time = Time.now
S3Client.should_receive(:upload_csv_by_path).with("#{Rails.root}/tmp/scalar_test_exporter.csv", nil, expires: time)
S3Client.upload_csv_by_path(file_name, nil, expires: time)

This way you could make sure that the time is the same in both statements, or you could use a gem like timecop to help you with this like @gotva suggested, timecop is very useful because it gives you the ability to freeze time, move forward and backwards in time, it's nice, for the same example you'd write this

Time.freeze
S3Client.should_receive(:upload_csv_by_path).with("#{Rails.root}/tmp/scalar_test_exporter.csv", nil, expires: 1.day.from_now)
S3Client.upload_csv_by_path(file_name, nil, expires: 1.day.from_now)
Time.return

Setting system time in rspec tests without changing system clock

before {Time.stub(:now) {Time.now.utc}}

With this, anywhere Time.now is called in your tests, it will return your system's time in UTC.

Example:

describe Time do
before {Time.stub(:now) {Time.now.utc}}

it "returns utc as my system's time" do
Time.now.utc?.should be_true
end
end


Related Topics



Leave a reply



Submit