Skip to content

Instantly share code, notes, and snippets.

@grauwoelfchen
Last active January 31, 2020 14:34
Show Gist options
  • Save grauwoelfchen/5e9cccf927ffbdb17acc to your computer and use it in GitHub Desktop.
Save grauwoelfchen/5e9cccf927ffbdb17acc to your computer and use it in GitHub Desktop.
Unit test example for cache in model class
class Book < ActiveRecord::Base
after_commit :flush_cache
def self.cached_find(id)
Rails.cache.fetch([name, id], expires_in: 30.mitues) do
where(:id => id).take!
end
end
private
def flush_cache
Rails.cache.delete([self.class.name, id])
end
end
require "test_helper"
class BookTest < ActiveSupport::TestCase
include CachingHelper
def test_cached_find_raises_exception_if_missing_id_is_given
assert_raise ActiveRecord::RecordNotFound do
Book.cached_find(0)
end
end
def test_cached_find_returns_cache_after_cache_was_created
with_caching do
book = books(:linux_book)
assert_equal book, Book.cached_find(book.id)
# mocha
# see https://github.com/freerange/mocha
# e.g.
# Book.expects(:where).with(:id => book.id).times(0)
# assert_equal book, Book.cached_find(book.id)
# minitest/mock
# see https://github.com/seattlerb/minitest/blob/master/lib/minitest/mock.rb
mock = Minitest::Mock.new
mock.expect(:take!, :not_called)
Book.stub(:where, mock) do
assert_equal book, Book.cached_find(book.id)
assert_raise MockExpectationError do
mock.verify
end
end
end
end
def test_cached_find_loads_exact_record_after_cache_was_destroyed
with_caching do
book = books(:linux_book)
assert_equal book, Book.cached_find(book.id)
# This will invoke `after_commit` callback by test_after_commit gem
# see https://github.com/grosser/test_after_commit
assert book.update_attribute(:title, "New Linux Book")
book.reload
# mocha
# e.g.
# Book::ActiveRecord_Relation.any_instance
# .expects(:take!).returns(book).times(1)
# Book.cached_find(book.id)
# Rails.cache.clear
# minitest/mock
# see https://github.com/seattlerb/minitest/blob/master/lib/minitest/mock.rb
mock = Minitest::Mock.new
mock.expect(:take!, book)
Book.stub(:where, mock) do
assert_equal book, Book.cached_find(book.id)
mock.verify
end
end
end
end
class BooksController < ApplicationController
def show
@book = Book.cached_find(params[:id])
end
end
module CachingHelper
def with_caching
cache_store_type_origin = Rails.application.config.cache_store
cache_store_origin = Rails.cache
Rails.application.config.cache_store = [
:memory_store, {:size => 64.megabytes }
]
Rails.cache = ActiveSupport::Cache::MemoryStore.new(
:expires_in => 1.minute
)
yield
ensure
Rails.cache.clear
Rails.cache = cache_store_origin
Rails.application.config.cache_store = cache_store_type_origin
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment