概要
例えば Sidekiq.redis { |c| c.get("hoge") }
みたいな使い方をしているときに redis にはアクセスしないでテストしたい場合があると思います
そんな場合に rspec-mocks を使ってブロックをスタブする方法を紹介します
環境
- macOS 10.14.3
- Ruby 2.5.1p57
実行コード
例えば以下のような感じで Sidekiq.redis
をコールしているとします
require 'sinatra/base'
require './worker.rb'
class Web < Sinatra::Base
get '/:key' do
Sidekiq.redis { |c|
return c.get(params[:key])
}
end
end
これを rspec-mocks を使ってスタブするテストを作成します
スタブテストコード
and_yield
を使うとブロック内の処理をスタブすることができます
ENV['RACK_ENV'] = 'test'
require './app.rb'
require 'rspec'
require 'rack/test'
describe "Web Tests" do
include Rack::Test::Methods
def app
Web
end
it "could be fetch a value from redis" do
redis = instance_double(Redis, :get => "fuga_test")
allow(Sidekiq).to receive(:redis).and_yield(redis)
get '/hoge'
expect(last_response.body).to eq "fuga_test"
end
end
これでテストすると Redis にはアクセスすることなくテストできます
応用
同じメソッド名で引数の key が異なる呼び出しをブロック内で複数しているとします
その場合は引数の key を正規表現を使って判断し引数に応じて別々のレスポンスを返却するように stub を定義します
require 'sinatra/base'
require './worker.rb'
class Web < Sinatra::Base
get '/:key' do
Sidekiq.redis { |c|
if c.get("fuga") == "fuga_test"
return c.get(params[:key])
end
}
end
end
ENV['RACK_ENV'] = 'test'
require './app.rb'
require 'rspec'
require 'rack/test'
describe "Web Tests" do
include Rack::Test::Methods
def app
Web
end
it "could be fetch a value from redis" do
redis = instance_double(Redis)
allow(redis).to receive(:get).with(/hoge/).and_return("hoge_test")
allow(redis).to receive(:get).with(/fuga/).and_return("fuga_test")
allow(Sidekiq).to receive(:redis).and_yield(redis)
get '/hoge'
expect(last_response.body).to eq "hoge_test"
end
end
allow(redis).to receive(:get).with(/hoge/).and_return("hoge_test")
を引数の key が異なる呼び出しごとに定義しています
これで c.get("fuga")
の場合は fuga_test
が返り c.get("hoge")
の場合は hoge_test
が stub から返るようになります
0 件のコメント:
コメントを投稿