Reputation: 5147
This is my Tag model and I don't know how can I test Rails.cache feature.
class Tag < ActiveRecord::Base
class << self
def all_cached
Rails.cache.fetch("tags.all", :expires_in => 3.hours) do
Tag.order('name asc').to_a
end
end
def find_cached(id)
Rails.cache.fetch("tags/#{id}", :expires_in => 3.hours) do
Tag.find(id)
end
end
end
attr_accessible :name
has_friendly_id :name, :use_slug => true, :approximate_ascii => true
has_many :taggings #, :dependent => :destroy
has_many :projects, :through => :taggings
end
Do you know how can it will be tested ?
Upvotes: 8
Views: 19907
Reputation: 4953
I agree with @chris-heald's answer. To make tests less brittle you could change your code this way:
def self.all_cached
Rails.cache.fetch('tags.all', expires_in: 3.hours) do
all_uncached
end
end
def self.all_uncached
Tag.order('name asc').to_a
end
and test it the following way:
describe Tag do
context 'retrieving all tags' do
let(:tag) { Tag.create! }
before do
allow(Tag).to receive(:all_uncached) do
fail 'Database hit!' if @database_hit
@database_hit = true
[tag]
end
end
context 'when the cache is populated' do
before { Tag.all_cached }
it 'should not hit the database' do
expect(Tag.all_uncached).to raise_error 'Database hit!'
expect(Tag.all_cached).to eq [tag]
end
end
end
end
Upvotes: 0
Reputation: 62658
Well, first, you shouldn't really be testing the framework. Rails' caching tests ostensibly cover that for you. That said, see this answer for a little helper you can use. Your tests would then look something like:
describe Tag do
describe "::all_cached" do
around {|ex| with_caching { ex.run } }
before { Rails.cache.clear }
context "given that the cache is unpopulated" do
it "does a database lookup" do
Tag.should_receive(:order).once.and_return(["tag"])
Tag.all_cached.should == ["tag"]
end
end
context "given that the cache is populated" do
let!(:first_hit) { Tag.all_cached }
it "does a cache lookup" do
before do
Tag.should_not_receive(:order)
Tag.all_cached.should == first_hit
end
end
end
end
end
This doesn't actually check the caching mechanism - just that the #fetch
block isn't invoked. It's brittle and tied to the implementation of the fetch block, so beware that as it will become maintenance debt.
Upvotes: 8