RSpec

RSpecのallow_any_instance_ofでブロック指定するときは第一引数に注意

自分用メモ。
リファレンス に書いてあることそのまま

ハマったこと

app/models/user.rb
class User
  def recommended_books(limit: 3)
    RecommendationService.new(self).recommended_books(max_recommendation_size: limit)
  end
end

みたいなメソッドがあったとして、RecommendationServiceは外部サービスなので、テストには不便。
RecommendationServiceの内部実装も知らんので、User#recommended_booksをモックすることにした。

これはOK

user = create(:user)
allow(user).to receive(:recommended_books) do |args|
  create_list(:book, args[:limit])
end

これはNG

allow_any_instance_of(User).to receive(:recommended_books) do |args|
  create_list(:book, args[:limit])
end

args[:limit] がnil になってハマる!

なんで???

第1引数は、レシーバーのオブジェクト!第2引数以降がメソッドの引数!

ってリファレンスに書いてあった。

なので、

allow_any_instance_of(User).to receive(:recommended_books) do |user, args|
  create_list(:book, args[:limit])
end

とすればよい。

まとめ

リファレンス はちゃんと読みましょう。