はじめに
先日つまずいた箇所と解決法をメモしています。もっといい方法などもありそうですが、それを見つけた際はまた書き直したいですね。
TL;DR
元のメソッドを呼びたいときはand_call_original
メソッドを使う。
allow(hoge_moc).to receive(:say).and_call_original
経緯
引数で特定の値を受け取った際の動作を定義する
テスト対象のファイルはこんな感じ。
test.rb
class Test
def test_method
hoge = Hoge.new
hoge.say("hello")
end
end
class Hoge
def say(message)
message
end
end
テストファイルはこんな感じ。
Hoge#say
で"hello"
という文字列を受け取った際に"hogehoge"
という文字列を返すようスタブする。
test_spec.rb
describe 'Test' do
context 'test_method' do
it 'returns hogehoge' do
hoge_moc = instance_double(Hoge)
allow(Hoge).to receive(:new).and_return(hoge_moc)
allow(hoge_moc).to receive(:say).with("hello").and_return("hogehoge")
expect(Test.new.test_method).eq "hogehgoe"
end
end
end
定義されていない引数を受け取ったときにエラーが発生する
先ほどのテストなら何の問題もなくテストが通る。
しかし定義されていない引数を受け取った時、このテストだとエラーをはいてしまう。
例えば先ほどのTestクラスが以下のようになったとする。
test.rb
class Test
def test_method
hoge = Hoge.new
hoge.say("undefined text")
hoge.say("hello")
end
end
すると先ほどのテストはこのようなエラーをはく。
Failures:
1) Test test_method returns hogehoge
Failure/Error: hoge.say("undefined text")
#<InstanceDouble(Hoge) (anonymous)> received :say with unexpected arguments
expected: ("hello")
got: ("undefined text")
Please stub a default value first if message might be received with other args as well.
# ./spec/test.rb:4:in `test_method'
# ./spec/test_spec.rb:11:in `block (3 levels) in <top (required)>'
長々と書いてあるが、要するに
「"hello"
を受け取るはずが"undefined text"
ってヤツを受け取っちまったよ!他の引数も入るならデフォルト値もスタブしてくれよ!」
といった感じ。
定義されていない引数を受け取ったときに元のメソッドを呼ぶ
今回は定義されていない引数を受け取ったとき、元のメソッドと同じ動きをしてもらいたかったので、デフォルトで元の動きをするように定義します。
test_spec.rb
describe 'Test' do
context 'test_method' do
it 'returns hogehoge' do
hoge_moc = instance_double(Hoge)
allow(Hoge).to receive(:new).and_return(hoge_moc)
allow(hoge_moc).to receive(:say).and_call_original
allow(hoge_moc).to receive(:say).with("hello").and_return("hogehoge")
expect(Test.new.test_method).eq "hogehgoe"
end
end
end
これで"hello"
以外の引数を受け取ったときに元のメソッドと同じ動きをしてくれます。