I feel like this is a not-so-much documented topic, at least I\'ve had a lot of trouble finding our about the best practices here.
I\'m fragment caching in the view usin
I use view specs to test cache expiration in views:
describe Expire::Employee, type: :view, caching: true do
def hour_ago
Timecop.travel(1.hour.ago) { yield }
end
def text_of(css, _in:)
Nokogiri::HTML(_in).css(css).text
end
let(:employee) { hour_ago { create :employee } }
def render_employees
assign(:employees, [employee.reload])
render(template: 'employees/index.html.erb')
end
alias_method :employees_list, :render_employees
context "when an employee's position gets changed" do
let(:position) { create :position, employee: employee }
before { hour_ago { position.update!(name: 'Old name') } }
let(:update_position) { position.update!(name: 'New name') }
it "should expire the employee's cache" do
expect { update_position }
.to change { text_of('.positions', _in: employees_list) }
.from(/Old name/).to(/New name/)
end
end
# similar spec case for home base assignment
end
where
Note that I tagged this spec with caching: true
. It enables caching before each test case and disables after it:
config.before(:each, caching: true) do
controller.perform_caching = true
end
config.after(:each, caching: true) do
controller.perform_caching = false
end
And you might want to add an example that checks that an employee is being actually cached
describe Expire::Employee, type: :view, caching: true do
context 'with an uncached employee' do
it 'should cache the employee' do
expect_any_instance_of(Employee)
.to receive(:current_positions).once
2.times { render_employees }
end
end
# other spec cases
end
Let me first say that in this answer, you may get more sympathy then fact. I've been struggling with these same issues. While I was able to get reproducible results for a particular test, I found that the results varied according to whether or not I ran one versus multiple specs, and within or without spork. Sigh.
In the end, I found that 99.9% of my issues disappeared if I simply enabled caching in my test.rb file. That might sound odd, but after some thought it was "correct" for my application. The great majority of my tests are not at the view/request layer, and for the few that are, doesn't it make sense to test under the same configurations that the user views?
While I was wrestling with this, I wrote a blog post that contains some useful test helpers for testing caching. You might find it useful.
Here is what I've used in my specs with caching enabled in my config/environments/test.rb
require 'spec_helper'
include ActionController::Caching::Fragments
describe 'something/index.html.erb' do
before(:each) do
Rails.cache.clear
render
end
it 'should cache my fragment example' do
cached_fragment = Rails.cache.read(fragment_cache_key(['x', 'y', 'z']))
cached_fragment.should have_selector("h1")
end
end