概要
rspecではテストをしやすくするために、メソッドをモックしたいときがよくあると思います。
下記の例では set_complex_config
メソッドにadmin?
メソッドが影響を受けるのですが、
set_complex_config
メソッドはすでにそれ自体のテストコードがあり、そのレスポンスのみ欲しいという状況です。
# コード例は適当です
class User
def admin?
res = set_complex_config
case res
when 'hoge'
'hoge'
when 'fuga'
'fuga'
end
end
def set_complex_config
# 複雑な処理
end
end
このような場合のモックの仕方として私は2通りのやり方が思いつくので、どちらが良いかを考えてみました。
mockの仕方
① singleton メソッドを定義してmockする
下記のように User クラスの set_complex_config メソッドを singleton メソッドで上書きする方法です。
let(:hoge_let) { 'hoge' }
it do
user = create(:user)
hoge_var = 'hoge'
user.define_singleton_method(:set_complex_config) { hoge_var }
user.set_complex_config => 動く
user.define_singleton_method(:set_complex_config) { hoge_let }
user.set_complex_config => wrong number of arguments (given 0, expected 2..3)
end
一見かっこいいですが、この場合、example内やbeforeブロック内で、define_singleton_method メソッドのブロックはlet変数を読むことができません。
② allow メソッドでmockする
allow メソッドでは問題なく動きます。
let(:hoge_let) { 'hoge' }
it do
user = create(:user)
allow(user).to receive(:attributes).and_return(hoge_let)
user.set_complex_config => 動く
end
結論
素直にallow().to receive().and_return()
を使った方が良さそうです。