LoginSignup
1
0

More than 1 year has passed since last update.

rspecのスタブで元のメソッドを呼ぶ

Posted at

はじめに

先日つまずいた箇所と解決法をメモしています。もっといい方法などもありそうですが、それを見つけた際はまた書き直したいですね。

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"以外の引数を受け取ったときに元のメソッドと同じ動きをしてくれます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0