This one had Adam and me stumped for a while. Trying to check that a method is only called on objects that respond to it:
describe "Foo#call_all_the_things" do
let(:foo_1) { stub :foo_1, bar: "hello" }
let(:foo_2) { stub :foo_2 }
subject { Foo.new foo_1, foo_2 }
it "only calls bar on objects that respond to it" do
foo_1.should_receive :bar
foo_2.should_not_receive :bar
subject.call_all_the_things(:bar)
end
end
class Foo
def initialize *things
@things = things
end
def call_all_the_things method
@things.each do |thing|
thing.send method if thing.respond_to? method
end
end
end
1) Foo#call_all_the_things only calls bar on objects that respond to it
Failure/Error: thing.send method if thing.respond_to? method
(Stub :foo_2).bar(no args)
expected: 0 times
received: 1 time
Hmm. Why is it calling bar
on the thing that doesn’t respond to it? Perhaps rSpec doubles don’t handle respond_to?
properly?
[1] pry(main)> require "rspec/mocks/standalone"
=> true
[2] pry(main)> foo = stub foo: 123
=> #
[3] pry(main)> foo.respond_to? :foo
=> true
[4] pry(main)> foo.respond_to? :bar
=> false
Nope.
FX: lightbulb above head
Of course! To do the should_not_receive
check, it needs to stub the method, which means it responds to it!
Two possible solutions: either let the fact that the missing method isn’t called be tested implicitly, or specify that when objects that don’t respond to the method exist, no NoMethodError
is raised.