debian-mirror-gitlab/spec/models/concerns/redis_cacheable_spec.rb
2023-05-27 22:25:52 +05:30

154 lines
4 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe RedisCacheable do
let(:model) do
Struct.new(:id, :attributes) do
def read_attribute(attribute)
attributes[attribute]
end
def cast_value_from_cache(attribute, cached_value)
cached_value
end
def has_attribute?(attribute)
attributes.has_key?(attribute)
end
end
end
let(:payload) { { name: 'value', time: Time.zone.now } }
let(:instance) { model.new(1, payload) }
let(:cache_key) { instance.__send__(:cache_attribute_key) }
before do
model.include(described_class)
end
describe '#cached_attribute' do
subject { instance.cached_attribute(payload.each_key.first) }
it 'gets the cache attribute' do
Gitlab::Redis::Cache.with do |redis|
expect(redis).to receive(:get).with(cache_key)
.and_return(payload.to_json)
end
expect(subject).to eq(payload.each_value.first)
end
end
describe '#cache_attributes' do
subject { instance.cache_attributes(payload) }
it 'sets the cache attributes' do
Gitlab::Redis::Cache.with do |redis|
expect(redis).to receive(:set).with(cache_key, payload.to_json, anything)
end
subject
end
context 'with existing cached attributes' do
before do
instance.cache_attributes({ existing_attr: 'value' })
end
it 'sets the cache attributes' do
Gitlab::Redis::Cache.with do |redis|
expect(redis).to receive(:set).with(cache_key, payload.to_json, anything).and_call_original
end
expect { subject }.to change { instance.cached_attribute(:existing_attr) }.from('value').to(nil)
end
end
end
describe '#merge_cache_attributes' do
subject { instance.merge_cache_attributes(payload) }
let(:existing_attributes) { { existing_attr: 'value', name: 'value' } }
before do
instance.cache_attributes(existing_attributes)
end
context 'with different attribute values' do
let(:payload) { { name: 'new_value' } }
it 'merges the cache attributes with existing values' do
Gitlab::Redis::Cache.with do |redis|
expect(redis).to receive(:set).with(cache_key, existing_attributes.merge(payload).to_json, anything)
.and_call_original
end
subject
expect(instance.cached_attribute(:existing_attr)).to eq 'value'
expect(instance.cached_attribute(:name)).to eq 'new_value'
end
end
context 'with no new or changed attribute values' do
let(:payload) { { name: 'value' } }
it 'does not try to set Redis key' do
Gitlab::Redis::Cache.with do |redis|
expect(redis).not_to receive(:set)
end
subject
end
end
end
describe '#cached_attr_reader', :clean_gitlab_redis_cache do
subject { instance.name }
before do
model.cached_attr_reader(:name)
end
context 'when there is no cached value' do
it 'reads the attribute' do
expect(instance).to receive(:read_attribute).and_call_original
expect(subject).to eq(payload[:name])
end
end
context 'when there is a cached value' do
it 'reads the cached value' do
expect(instance).not_to receive(:read_attribute)
instance.cache_attributes(payload)
expect(subject).to eq(payload[:name])
end
end
it 'always returns the latest values' do
expect(instance.name).to eq(payload[:name])
instance.cache_attributes(name: 'new_value')
expect(instance.name).to eq('new_value')
end
end
describe '#cast_value_from_cache' do
subject { instance.__send__(:cast_value_from_cache, attribute, value) }
context 'with runner contacted_at' do
let(:instance) { Ci::Runner.new }
let(:attribute) { :contacted_at }
let(:value) { '2018-05-07 13:53:08 UTC' }
it 'converts cache string to appropriate type' do
expect(subject).to be_an_instance_of(ActiveSupport::TimeWithZone)
end
end
end
end