I use cache_fu for caching my rails application. I use a “fat models, skinny controllers strategy”. This means that my Author model has code like this:
def cached_books
get_cache(:author_books) do
Book.find_by_author_id(self.id)
end
end
This method caches all books belonging to an author. Cache fu does not cache belongs_to or has_(one|many) relationships, and that’s why we have this method. But this also means that if we add a book to an author, we must also expire the author records cache. This can all be done with cache_fu. The problem is that these relationships might get quite complicated and it would be nice to be able to write some specs that test that everything behaves as intended.
Chris Wanstrath, the author of cache_fu, suggests using mocha to stub everything about, but didn’t want to emulate the caching behavior and then test if the behavior is right. That is fine if you test the cache_fu plugin, but not fine if you need to test if your application uses the cache_fu plugin correctly. What I wanted was to turn on caching while running my specs and then query the cache to see if things are actually cached properly.
This first this I tried was turning on caching in the “test” environment. Turns out that it is not a good idea, as a lot of specs go into some kind of recursive error when you do that. Caching should be off by default in test. I needed a way to turn on the cache functions in a given spec.
Long story short: for unit testing you add the following function to your model:
class << self
def reenable_cache_for_test
class << self
alias_method :fetch_cache, :fetch_cache_without_disabled
alias_method :set_cache, :set_cache_without_disabled
alias_method :expire_cache, :expire_cache_without_disabled
end
end
end
You call this method in your spec like this:
it "should cache author" do
Author.reenable_cache_for_test
CACHE.flush_all
CACHE.get('Author:1').should == nil
author = Author.get_cache(1)
author.should != nil
CACHE.get('Author:1').should == author
CACHE.get('Author:1:books').should == nil
books = user.cached_books
CACHE.get('Author:1:books).should == books
end
Fragment caching is a bit different, in you controller spec you do this:
it "fragment should be cached on get" do
ActionController::Base.perform_caching = true
ActsAsCached.config.clear
config = YAML.load_file( File.dirname(__FILE__) + '/../../vendor/plugins/cache_fu/defaults/memcached.yml.default')
config['test'] = config['development'].merge('benchmarking' => false, 'disabled' => false)
ActsAsCached.config = config
ActsAsCached::FragmentCache.setup!
CACHE.flush_all
… and then do your cache checking.
Popularity: 100% [?]
