Redis ist ein Eimer, eine Deponie oder einfach ein Key/ Value Speicher. Es ist sehr praktisch zum Cachen.
Beim Testen der darüber liegenden Business Logik sollten einige Dinge beachtet werden.
Redis Business Logik
Zunächst soll ein einfacher Redis Wrapper als beispielhafte Implementierung einer Business Logik (basierend auf Redis) dienen.
Zunächst soll als beispielhafte Implementierung einer Business Logik, basierend auf Redis, ein einfacher Redis Wrapper dienen.
Ziel dieses Wrappers ist es, Objekte in Redis abzulegen, allerdings mit einem eindeutigen Key.
Ein Anwendungsfall könnten ActiveRecord Objekte sein, da sie anhand ihrer ID nicht eindeutig in Redis abgelegt werden können, da es mehrere unterschiedliche ActiveRecord Objekte mit der gleichen ID geben kann.
Dieser Wrapper bildet einen den eindeutigen Key aus dem Klassennamen und seiner ID:
module Model
class Cache
attr_reader :record
def initialize(record)
@record = record
end
def dump(value)
redis.set key, value
end
def find
redis.get key
end
private
def key
"#{record.class}:#{record.id}"
end
def redis
@redis ||= Redis.new
end
end
end
Er kann dann anhand des Keys, einen Wert in Redis ablegen und auch wiederfinden.
Es gibt ähnliche Ansätze in bereits bestehenden Ruby Gems.
Diese Implementierung soll mit RSpec getestet werden.
Redis Spec Helper
Zunächst macht es Sinn, einen Redis Spec Helper einzuführen, der sich um Aufgaben kümmert, die sich für jeden Test wiederholen und keine Nutzen für die Lesbarkeit der Spezifikation bringen. Ein minimaler redis_spec_helper.rb:
RSpec.configure do |config|
config.before(:each) { redis.flushdb }
config.after(:each) { redis.quit }
end
Er leert alle Redis Speicherungen vor jedem Test und beendet nach jedem Test die Verbindung zu Redis.
Es könnte auch das Setzen einer bestimmten Redis Datenbankinstanz beinhalten oder andere Test Helper.
Unit Test Vorbereitungen für Redis
Der Unit Test bedarf einiger Testfallvorbereitungen. Insbesondere das testbare Model::Cache Objekt als subject:
require 'rspec'
require 'redis_helper'
TestModel = Struct.new :id
RSpec.describe Model::Cache do
let!(:redis) { Redis.new }
let!(:model) { TestModel.new rand(1..10) }
let!(:model_key) { "TestModel:#{model.id}" }
subject { Model::Cache.new model }
describe '#model' do
it 'returns the model' do
expect(subject.model).to be model
end
end
end
Außerdem wurden einige Variablen angelegt, nämlich: * redis (ein unabhängiger Redis Datenbankzugriff) * model (ein Struct Objekt mit einer zufälligen ID, dass das Model darstellt) * model_key (der erwartete Model Key) Schließlich wird schon einmal der model accessor model getestet.
Unit tests mit Redis
Die Tests für die beiden Methoden dump und find decken dann das erwartete Verhalten ab:
require 'rspec'
require 'redis_helper'
TestModel = Struct.new :id
RSpec.describe Model::Cache do
let!(:redis) { Redis.new }
let!(:model) { TestModel.new rand(1..10) }
let!(:model_key) { "TestModel:#{model.id}" }
subject { Model::Cache.new model }
describe '#model' do
it 'returns the model' do
expect(subject.model).to be model
end
end
describe '#dump' do
before { subject.dump 'test' }
it 'dumps the models key into Redis' do
expect(redis.keys).to eq([model_key])
end
it 'dumps the value for the models key into Redis' do
expect(redis.get(model_key)).to eq('test')
end
end
describe '#find' do
it 'finds the records value' do
redis.set model_key, 'test'
expect(subject.find).to eq('test')
end
context 'when dumps an Integer' do
it 'returns the value as a String' do
redis.set model_key, 123
expect(subject.find).to eq('123')
end
end
end
end