🧪
allow_any_instance_of を書き換える
rubocop に怒られるので書き換えるわけですが
# bad
describe MyClass do
before { allow_any_instance_of(MyClass).to receive(:foo) }
end
# good
describe MyClass do
let(:my_instance) { instance_double(MyClass) }
before do
allow(MyClass).to receive(:new).and_return(my_instance)
allow(my_instance).to receive(:foo)
end
end
bad
のコードだと foo
以外を呼ばれた時には「元の挙動」をしてくれるのに good
の書き換えは instance_double にすり替えており、 foo
以外のコールが全部エラーになる。挙動変わってんじゃん。困るんだよねそういうの。
で、正しい書き換えを伝授するのでどうぞご利用ください。
# very good
describe MyClass do
before do
allow(MyClass).to receive(:new).and_wrap_original do |method, *args, **kwargs, &block|
method.call(*args, **kwargs, &block).tap do |instance|
allow(instance).to receive(:foo)
end
end
end
end
こうすると、 instance
には double ではない本物のインスタンスが入りますんで、そこへ色々仕掛けることができます。
おまけ: rspec playground
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "rspec"
end
class Hoge
def foo = "foo"
def bar = "bar"
end
RSpec.describe Hoge do
before do
allow(Hoge).to receive(:new).and_wrap_original do |method, *args, **kwargs, &block|
method.call(*args, **kwargs, &block).tap do |instance|
allow(instance).to receive(:bar).and_return('stubbed')
end
end
end
it do
hoge = Hoge.new
expect(hoge.foo).to eq('foo')
expect(hoge.bar).to eq('stubbed')
puts hoge.bar
end
end
RSpec::Core::Runner.invoke
Discussion