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 web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
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)