Rspecでスタブを使ったときのメモ
こんなコードがあったんです。
メールアドレス変更をするときに、ユーザーIDと新メールアドレスとトークンを持つモデルのテストで、トークンがかぶったらマズイからbefore_saveでunique_tokenという、渡されたトークンが既に存在しないか確認するメソッドを呼ぶという。
attr_accessible :email before_save do |email_change| email_change.token = EmailChange.unique_token(SecureRandom.urlsafe_base64) end def self.unique_token(token) if EmailChange.where(token: token).count > 0 EmailChange.unique_token(SecureRandom.urlsafe_base64) else token end end
このunique_tokenのテストを書くときの問題として、トークンかぶりのテストをするときは、任意のトークンをDBに入れておくしかないんだけど、もともとランダムな値を返すメソッドをbefore_saveで呼んでいるので、ふつうにやるとそれができないという点。
こんなときにはスタブを使う。こんな感じに書いてみた。
describe "unique_token" do context "the token has already been taken" do before do EmailChange.stub(:unique_token).and_return('token') @email_change.save EmailChange.unstub!(:unique_token) end it { expect(EmailChange.unique_token('token')).not_to eq('token') } end context "the token has NOT already been taken" do before do @email_change.save end it { expect(EmailChange.unique_token('token')).to eq('token') } end end
いちど任意のトークンを保存したあとは、通常通りunique_tokenが動いてくれないと困るのでEmailChange.unstub!(:unique_token)しておいた。
便利やなぁ。