Rspec: Natively control Time with Rails
Guillaume Briday
1 minute
You can natively control Time in your specs with Rails.
You don't need additional gems like the really good Timecop. Rails has a built-in mechanism to do exactly the same thing.
How to use it?
Include the ActiveSupport::Testing::TimeHelpers module in your spec/rails_helper.rb
config file.
# spec/rails_helper.rb
RSpec.configure do |config|
config.include ActiveSupport::Testing::TimeHelpers
end
Now you can use it in your hooks to change the time in all your tests:
RSpec.describe 'Post' do
before do
travel_to Time.new(2023, 12, 4, 16, 30) # Mon, 04 Dec 2023 16:30:00
# Now, Time.now (and all Time or Date methods), will always return `Time.new(2023, 12, 4, 16, 30)`.
# Here, Time.current.yesterday will return Sun, 03 Dev 2023 16:30:00.
end
end
Thanks to the #after_teardown
method, you don't need to use the around
hook:
# ❌ Don't do this.
RSpec.describe 'Post' do
around do |test|
travel_to Time.new(1994) do
test.run
end
end
end
# ✅ Do
RSpec.describe 'Post' do
before do
travel_to Time.new(1994)
end
end
You can also use it directly in your it
:
RSpec.describe 'Post' do
let(:post) { create(:post, published_on: Date.new(2021, 5, 14)) }
it 'works' do
travel_to Date.new(2020) do # Not published yet in 2020
expect(post.published?).to be(false)
end
# But published now because we are after May 14, 2021
expect(post.published?).to be(true)
end
end
It's really handy when you when to predict results and not rely on current time.
Check out the documentation for more information: ActiveSupport::Testing::TimeHelpers.