🕌
RSpec で任意のメソッドが呼ばれたかどうかをテストする
テストを書くときに『内部で任意のメソッドが呼ばれていること』を担保したい事があります。
そういう場合は RSpec
では receive
マッチャで検証する事ができます。
class User < Struct.new(:name)
def exists?
find!(name)
end
def find!(name)
# ...
end
end
require "rspec"
RSpec.describe User do
describe "#exists?" do
subject { user.exists? }
let(:user) { User.new(name: "homu") }
it do
# it 内で user,find!("homu") が呼び出されていることを担保するテストになる
# with でメソッドの引数を指定する事ができる
expect(user).to receive(:find!).with(user.name)
subject
end
# これは失敗する
it do
expect(user).to receive(:find!).with(user.name)
# user.find! が呼び出されない
# subject
end
# これは失敗する
it do
expect(user).to receive(:find!).with("mami")
# user.find! は呼び出されているが意図する引数ではない
subject
end
# これは成功する
it do
expect(user).to receive(:find!).with(user.name)
# subject や User#exists? 経由で呼び出されている必要はない
user.find!("homu")
end
end
end
こんな感じで『レシーバに対して任意のメソッドが呼び出されているかどうか』を検証するテストを記述することができます。
内部の実装に依存する場合はこういうテストを書きたいときもありますねー。
Discussion