RSpec の and_wrap_original(&block)とand_call_original

2024-09-24

allow(obj).to receive(:method, &block)

引数を block の引数に取るので、値によって分岐が可能。

allow(instance).to receive(:method) do |args|
  case args[:opt]
  when xxxx
    ...
  else
    ...
  end
end

and_wrap_original

and_call_originalENV の上書きの際によく見る。 まだこれがぱっと書けない。

# これだけを指定すると、[] が全部置き換わってしまう
allow(ENV).to receive(:[]).with("HOGE").and_return(1)

# []はオリジナルをコールし、"HOGE"のときだけ置き換えるのを以下のようにする
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:{}).with("HOGE").and_return(1)

参考: https://linyclar.github.io/rails_memos/development_tools/rspec_mocks_memo/

and_wrap_original

and_wrap_original は block で original_method を wrap することで上書きできるし、前後に処理を書くことで副作用を発生させることもできる。 これもさらっとは書けない。

allow(api).to receive(:large_list).and_wrap_original do |original_method, *args, &block|
  # ↓の前後に処理を書くことで副作用を発生させることも可能
  original_method.call(*args, &block).first(10) # ここは 10 件に絞って返している
end

and_return

これは可変長引数で、 n 番目の引数が n 回目の呼び出し時の返り値になる。

and_return(1, 2, 3) で 1 回目呼び出しは 1, 2 回目呼び出しは 2, 3 回目以降の呼び出しは 3 を返すようにできる。