Read more

How to: Rails cache for individual rspec tests

Emanuel
June 27, 2017Software engineer at makandra GmbH

Rails default config uses the ActiveSupport::Cache::NullStore and disables controller caching Show archive.org snapshot for all environments except production:

config.action_controller.perform_caching = false
config.cache_store = :null_store
Illustration UI/UX Design

UI/UX Design by makandra brand

We make sure that your target audience has the best possible experience with your digital product. You get:

  • Design tailored to your audience
  • Proven processes customized to your needs
  • An expert team of experienced designers
Read more Show archive.org snapshot

If you want to test caching you have at least two possibilities:

  1. Enable caching for every test (not covered by this card and straightforward)
  2. Enable caching for individual test

Enable caching for individual test (file cache)

1. Leave the default configuration
2. Add a caching helper which gives you a unique file caching path for parallel tests:

module CachingHelpers
  def file_caching_path
    path = "tmp/test#{ENV['TEST_ENV_NUMBER']}/cache"
    FileUtils::mkdir_p(path)

    path
  end
end

RSpec.configure do |config|
  config.include CachingHelpers
end

3. Now stub the Rails cache and clear it before each example:

RSpec.describe SomeClass
  let(:file_cache) { ActiveSupport::Cache.lookup_store(:file_store, file_caching_path) }
  let(:cache) { Rails.cache }
  
  before do
    allow(Rails).to receive(:cache).and_return(file_cache)
    Rails.cache.clear
  end
  
  it do
    expect(cache.exist?('some_key')).to be(false)
    
    cache.write('some_key', 'test')
    
    expect(cache.exist?('some_key')).to be(true)
  end
end

Enable caching for individual test (memory store)

1. Leave the default configuration
2. Now stub the Rails cache and clear it before each example:

RSpec.describe SomeClass
  # memory store is per process and therefore no conflicts in parallel tests
  let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) } 
  let(:cache) { Rails.cache }
  
  before do
    allow(Rails).to receive(:cache).and_return(memory_store)
    Rails.cache.clear
  end
  
  it do
    expect(cache.exist?('some_key')).to be(false)
    
    cache.write('some_key', 'test')
    
    expect(cache.exist?('some_key')).to be(true)
  end
end
Emanuel
June 27, 2017Software engineer at makandra GmbH
Posted by Emanuel to makandra dev (2017-06-27 12:14)