サンプルコード
トップレベルに定義したhoge
メソッドをモックして、モックできたことの検証を行うテストです。
hoge_spec.rb
require 'rspec/core'
def hoge
'👍'
end
RSpec.describe 'トップレベルに定義されたメソッドをモックする' do
it 'モック前に👍を返し、モック後に👎を返す' do
expect(hoge).to eq '👍'
allow_any_instance_of(Object).to receive(:hoge).and_return('👎')
expect(hoge).to eq '👎'
end
end
なぜ成立するのか?
モックを行っている箇所は下記のコードです。
Objectクラスに定義されたインスタンスメソッド#hoge
をモックしています。
allow_any_instance_of(Object).to receive(:hoge).and_return('👎')
トップレベルで定義したメソッドは Objectクラスのprivateインスタンスメソッドとして定義されるため、上記のコードでモックが可能になるという原理です。
参考: Ruby 3.1 リファレンスマニュアル object main
そもそもトップレベルに定義したメソッドをモックするような機会が在ってはいけない
トップレベルにメソッドを定義した場合、
呼び出し箇所が分かり辛かったり、意図せず上書きしてしまうといった問題があります。
利用できるスコープはできるだけ狭めたいものです。
下記の記事ではRubyのRefinements機能を使ってスコープを限定する方法を紹介してるので、
参考にしてください。